先月からの売上減少を可視化してみる

とあるゲーム会社のソシャゲの売り上げが、先月と比べて落ちた。 市場的にも、ゲーム的にもまだまだ伸びると考えられるため、会社で大きな問題となり、原因を究明することに。

今回与えられているデータは三つ。

  • DAU(Daily Active User:1日1回以上アクセスしたユーザーのデータ)

  • DPU(Daily Payment User:1日1円以上課金したユーザーのデータ)

  • Install(ユーザーごとにゲームを利用開始した日付が記録されたデータ)

データを確認

dau_df.head()
log_date app_name user_id
0 2013-06-01 game-01 116
1 2013-06-01 game-01 13491
2 2013-06-01 game-01 7006
3 2013-06-01 game-01 117
4 2013-06-01 game-01 13492
dpu_df.head()
log_date app_name user_id payment
0 2013-06-01 game-01 351 1333
1 2013-06-01 game-01 12796 81
2 2013-06-01 game-01 364 571
3 2013-06-01 game-01 13212 648
4 2013-06-01 game-01 13212 1142
install_df.head()
install_date app_name user_id
0 2013-04-15 game-01 1
1 2013-04-15 game-01 2
2 2013-04-15 game-01 3
3 2013-04-15 game-01 4
4 2013-04-15 game-01 5

三つのデータフレームをuser_idで結合させる。 この時、dpuは全ユーザーデータではないので、データが欠損しないように気をつける。

dau_install_df = pd.merge(dau_df, install_df, on='user_id', how='left')
all_df = pd.merge(dau_install_df, dpu_df, on=['user_id', 'log_date'], how='outer')

確認

all_df.head()
log_date app_name_x user_id install_date app_name_y app_name payment
0 2013-06-01 game-01 116 2013-04-17 game-01 NaN NaN
1 2013-06-01 game-01 13491 2013-06-01 game-01 NaN NaN
2 2013-06-01 game-01 7006 2013-05-03 game-01 NaN NaN
3 2013-06-01 game-01 117 2013-04-17 game-01 NaN NaN
4 2013-06-01 game-01 13492 2013-06-01 game-01 NaN NaN

さて、これを見るとNot a Numberが存在していて、さらにapp_nameも複数存在してしまっているので、これを処理していく(NaNは0で埋める)

app_names = ['app_name', 'app_name_x', 'app_name_y']
all_df = all_df.drop(app_names, axis=1)
all_df = all_df.fillna(0)

確認してみる

all_df.head()
log_date user_id install_date payment
0 2013-06-01 116 2013-04-17 0.0
1 2013-06-01 13491 2013-06-01 0.0
2 2013-06-01 7006 2013-05-03 0.0
3 2013-06-01 117 2013-04-17 0.0
4 2013-06-01 13492 2013-06-01 0.0

スッキリしました。

さて、本によると、先月と今月の違いを見たいため、log_date、install_dateを月次に変更する。さらに、それらが一致するかしないかで、ユーザーが、新規か既存かの情報を加えたいとのこと。

logmonth = []
for k in range(len(all_df["log_date"])):
    str = all_df["log_date"][k]
    str_list = list(str)
    str_changed = str_list[5]+str_list[6]
    fin_str = ''.join(str_changed)
    logmonth.append(fin_str)
    
all_df["log_month"] = logmonth
installmonth = []
for k in range(len(all_df["install_date"])):
    str = all_df["install_date"][k]
    str_list = list(str)
    str_changed = str_list[5]+str_list[6]
    fin_str = ''.join(str_changed)
    installmonth.append(fin_str)
    
all_df["install_month"] = installmonth
new_one = []
for i in range(len(all_df["log_date"])):
    if all_df["log_month"][i] == all_df["install_month"][i]:
        new_one.append(0)
    else:
        new_one.append(1)
all_df["new(0)/old(1)"] = new_one
all_df.head()
log_date user_id install_date payment log_month install_month new(0)/old(1)
0 2013-06-01 116 2013-04-17 0.0 06 04 1
1 2013-06-01 13491 2013-06-01 0.0 06 06 0
2 2013-06-01 7006 2013-05-03 0.0 06 05 1
3 2013-06-01 117 2013-04-17 0.0 06 04 1
4 2013-06-01 13492 2013-06-01 0.0 06 06 0

多分もっと簡単な方法があるのだろうとは思いつつも、何しろ初学者なので強引に行ってしまった。

さて。本によると、この後、アクセスした月と新規か既存かの情報で、合計課金額を集計している。

payment_df = all_df.sort_values(by="user_id").groupby(["log_month", "new(0)/old(1)"]).sum()
payment_df
user_id payment
log_month new(0)/old(1)
06 0 604911660 49837.0
1 307222419 177886.0
07 0 592521566 29199.0
1 507666653 177886.0

user_idまで合計されてしまった。笑 取り除く。

payment_df = payment_df.drop("user_id", axis=1)
payment_df
payment
log_month new(0)/old(1)
06 0 49837.0
1 177886.0
07 0 29199.0
1 177886.0

さて、集計が終わったので、可視化してみる。

payment_df.plot(kind='bar', stacked=True)
plt.show()

f:id:icchy333:20180211185344p:plain

結果

6月と7月の売り上げを新規/既存ユーザーで層別化したところ、既存ユーザーの合計課金額には変化が見られないが、新規ユーザー総合課金額が減っている。

次の課題

この課金額の減少の原因を調べるために、登録ユーザー数の推移やどの課金額の層が減っているかを見て行く。