Pythonデータ分析 100本ノック5章の解説

お疲れさまです、Yuinaです🍵

本日は、Pythonの100本ノック・第5章の解説をお届けします。

使用している環境は以下のとおりです。

  • 実行環境:Google Colaboratory
  • OS:macOS

どうぞよろしくお願いいたします!

ノック41本目:データの読み込みと整形

import pandas as pd
customer = pd.read_csv('/content/customer_join.csv')
uselog_months = pd.read_csv('/content/use_log_months.csv')

5章ではジムの利用者データについて分析をしています。

まずはcustomer_join.csvとuse_log_months.csvを取り込みます。

customer_join.csvの中身はこんな感じです。

※おさまらなかったので画像2枚にしました。

会員区分やキャンペーン区分など詳細な会員データが入っているファイルみたいですね。

use_log_month.csvはこちらです。

ジムの利用履歴データみたいです。

ここからは、当月と過去1ヶ月の利用回数を集計したデータを作成します。

year_months = list(uselog_months['年月'].unique()) 
uselog = pd.DataFrame()

まず、uselog_monthsのデータフレームから年月(カラム名)のデータを取得します。

続いて、uselog = pd.DataFrame()で当月と前月のデータを統合したデータを格納する空のデータフレームを用意します。

for i in range(1,len(year_months)):
  tmp = uselog_months.loc[uselog_months["年月"]==year_months[i]].copy()
  tmp.rename(columns={"count":"count_0"},inplace=True)

  tmp_before = uselog_months.loc[uselog_months["年月"]==year_months[i-1]].copy()
  del tmp_before["年月"]
  tmp_before.rename(columns={"count":"count_1"},inplace=True)

当月分のデータを入れ込んでいきます。

for文ですが、最初の月には前月データがないため、1からループを開始します。

uselog_months.loc[uselog_months[“年月”]==year_months[i]].copy()は、

uselog_monthsの中から、年月のカラムのデータが特定の月と一致する行だけを取り出します。

最後にcount 列をcount_0に名前変更します。

続いて先月分のデータを見ていきます。

tmp_before = uselog_months.loc[uselog_months[“年月”]==year_months[i-1]].copy()は

uselog_monthsの年月のカラムから前月のデータを抽出し、削除します。

最後にcount列をcount_1に名前変更します。

続いて、データをマージ(結合)していきます。

tmp = pd.merge(tmp,tmp_before,on="customer_id",how="left")

当月(tmp)と前月(tmp_before)の利用回数を横並びにしたものをtmpに代入します。

uselog = pd.concat([uselog,tmp],ignore_index=True)

作成した当月+前月のデータをuselogに追加します。

結果こんな表が出来上がりました。

<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; /*width:300px*/;"><tbody><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; /*width:44px*/ width:86px;"><a href="https://rpx.a8.net/svt/ejp?a8mat=453FFM+DG1FLE+2HOM+BWGDT&rakuten=y&a8ejpredirect=https%3A%2F%2Fhb.afl.rakuten.co.jp%2Fhgc%2Fg00s3dw4.2bo11f3f.g00s3dw4.2bo12678%2Fa25042272339_453FFM_DG1FLE_2HOM_BWGDT%3Fpc%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Fautumn1%252F2831-021%252F%26amp%3Bm%3Dhttp%253A%252F%252Fm.rakuten.co.jp%252Fautumn1%252Fi%252F10269760%252F%26amp%3Brafcid%3Dwsc_i_is_33f72da33714639c415e592c9633ecd7" rel="nofollow"><img border="0" alt="" src="https://thumbnail.image.rakuten.co.jp/@0_mall/autumn1/cabinet/apide2024saika/image01/2831-021.jpg?_ex=64x64" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a href="https://rpx.a8.net/svt/ejp?a8mat=453FFM+DG1FLE+2HOM+BWGDT&rakuten=y&a8ejpredirect=https%3A%2F%2Fhb.afl.rakuten.co.jp%2Fhgc%2Fg00s3dw4.2bo11f3f.g00s3dw4.2bo12678%2Fa25042272339_453FFM_DG1FLE_2HOM_BWGDT%3Fpc%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Fautumn1%252F2831-021%252F%26amp%3Bm%3Dhttp%253A%252F%252Fm.rakuten.co.jp%252Fautumn1%252Fi%252F10269760%252F%26amp%3Brafcid%3Dwsc_i_is_33f72da33714639c415e592c9633ecd7" rel="nofollow">アマノフーズ&永谷園食卓セット BS-25R 内祝い お返し ギフトセット 出産内祝い 結婚内祝い お供え 御供 香典返し 粗供養 快気祝い 快気内祝い</a></p><p style="color:#666; margin-top:5px line-height:1.5;">価格:<span style="font-size:14px; color:#C00; font-weight:bold;">1620円</span><br/><span style="font-size:10px; font-weight:normal;">(2025/4/23 00:01時点)</span><br/><span style="font-weight:bold;">感想(0件)</span></p></td></tr></tbody></table>
<img border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=453FFM+DG1FLE+2HOM+BWGDT" alt="">

ノック42本目:退会前月の顧客データ作成

このジムは月末までに退会申請をして、翌月末で退会できるシステムです。

退会を未然に防ぐことが目的であるため、退会前月のデータを作成します。

from dateutil.relativedelta import relativedelta

relativedeltaのデータは、timedeltaと同じように日付や日付時刻に足したり引いたりできます。 relativedeltaは、dateutil.relativedeltaモジュールで定義されています。「Xヶ月後」「X年後」を計算できます(参照)

exit_customer = customer.loc[customer["is_deleted"]==1].copy()

customer データから、退会した顧客(is_deleted == 1)だけを取り出して新しいデータフレームを作成します。

exit_customer["exit_date"] = None

exit_date(退会前月)の入れ物を準備します。

exit_customer["end_date"] = pd.to_datetime(exit_customer["end_date"])

次にend_date(退会日)を日時型に変換し、それを元に退会前月データの準備します。

ちょっとわかりにくかったので別の書き方をしてみました。

# 日付として扱うために型変換
exit_customer["end_date"] = pd.to_datetime(exit_customer["end_date"]) 
# 1ヶ月引いた日付をまとめて計算
exit_customer["exit_date"] = exit_customer["end_date"] - pd.DateOffset(months=1) 
# 形式変換
exit_customer["年月"] = exit_customer["exit_date"].dt.strftime("%Y%m")

exit_customerはこのように表示されました。

次にuselogのカラム年月を文字列にして、exit_customerのカラム年月と形式を揃えています。

uselog["年月"] = uselog["年月"].astype(str)
exit_uselog = pd.merge(uselog, exit_customer, on=["customer_id", "年月"], how="left")

ここではuselog と exit_customer を「customer_id と 年月 が一致するもの同士」で結合します。

その結果,exit_customerはこのようになりました。

欠損値(NaN)がいっぱいあります。

データが欠損していないものだけ残して、あとは除外します。

exit_uselog = exit_uselog.dropna(subset=["name"])
print(len(exit_uselog))
print(len(exit_uselog["customer_id"].unique()))
exit_uselog.head()

綺麗になりました。

まとめ

今回はデータの読み込みと整形、そして退会前月の退会顧客のデータを作成しました。

次回は継続顧客のデータの作成からやっていきます。

ありがとうございました。

コメント

タイトルとURLをコピーしました