今回は会社の実務で利用した、Pythonのpandasによる分析手法を紹介する。
実務ではECサイトのマーケティングを行っているのだが、今回は1ヶ月の日にち(1〜31日まで)を5日ごと6つの階級に分け、どの日付範囲が最も売上が高いのかを分析してみた。
サンプルデータフレームの用意
まずは分析の対象となるデータセットを用意する。
本来であれば、実務で利用しているシステムのデータベースやCSVからデータを読み込むのだが、今回はサンプルとして以下のデータフレームを用意した。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.normal(100000, 20000, 1000),
index=pd.date_range('2017/01/01', periods=1000),
columns=['uriage'])
一応解説しておくと、4行目のrandom.normal関数は、第一引数に平均値、第二引数に標準偏差、第三引数に生成する配列の要素数を指定し、引数に与えた値に基づいた正規分布した乱数を生成する。
今回はindexに2017年1月から1000日間の日付範囲を指定し、1000日間の売上データを生成してみた。
さらにこのデータフレームに対し、「日」の値を格納した列を追加し、小数となっている売上データを整数に型変換してみた。
# 列dayに「日」を追加
df['day'] = df.index.day
# 列numを小数から整数に変換
df['uriage'] = df['uriage'].astype(int)
ここまでの処理を終えたデータフレームを確認すると以下のようになる。
uriage day
2017-01-01 77241 1
2017-01-02 122879 2
2017-01-03 131097 3
...
2019-09-25 91474 25
2019-09-26 78731 26
2019-09-27 105774 27
[1000 rows x 2 columns]
cut関数でビン分割
pandasのcut関数で、データフレームをビン分割することができる。
第一引数に対象のデータフレームを、第二引数に分割ルールを指定する。
今回は日が31と割り切れない値なので、リストに境界となる値を指定する方式を採った。
※この他、指定した整数で等間隔に分割する方法などもある。
pd.cut(df['day'], [0, 5, 10, 15, 20, 25, 31])
# 2017-01-01 (0, 5]
# 2017-01-02 (0, 5]
# 2017-01-03 (0, 5]
# 2017-01-04 (0, 5]
# 2017-01-05 (0, 5]
# 2017-01-06 (5, 10]
# 2017-01-07 (5, 10]
# 2017-01-08 (5, 10]
# 2017-01-09 (5, 10]
# 2017-01-10 (5, 10]
# 2017-01-11 (10, 15]
# 2017-01-12 (10, 15]
# 2017-01-13 (10, 15]
# 2017-01-14 (10, 15]
# 2017-01-15 (10, 15]
...
分割したビンごとにグルーピングして平均を算出する
これで各行に階級を設定することができたので、今度はこれを応用して階級ごとのグルーピングをおこなう。
groupby関数でグルーピングし、meanでグループごとの平均値を算出する。
df_rng_5day = df.groupby(pd.cut(df['day'], [0, 5, 10, 15, 20, 25, 31])).mean()
結果は次のとおりとなる。
df_rng_5day['uriage']
# day
# (0, 5] 101388.733333
# (5, 10] 101457.206061
# (10, 15] 100264.648485
# (15, 20] 101313.951515
# (20, 25] 102257.654545
# (25, 31] 99083.628571
# Name: uriage, dtype: float64
うまく日付範囲ごとの売上平均値が取得できた。
ちなみに実際の業務ではこの分析手法により、月初、月末が最も売れ行きが良いことが分かった。
そしてこの結果を、広告予算の配分を決める判断材料として使うことができた。