どうも、solobochiのbochiです。
SIGNATEの銀行顧客マーケティングデータ分析について、前回Rでの分析についてまとめたので、同様にpythonでのデータ分析(今回はLightGBM)についてまとめておきます。
目次
1.概要
データ分析コンテストで有名なKaggleの日本版とも呼ばれるSIGNATEのデータ分析問題を扱います。
- 銀行の定期預金申込キャンペーンについてキャンペーンデータから結果(定期預金のために口座開設したか)を予測する。
<背景と目的>
銀行の定期預金申込キャンペーンについて、その効果を測定したい。
具体的には、どのような顧客にどのようなアプローチでキャンペーンを打つとより効果的に定期預金申込に繋がるのかを分析したい。
そのためにキャンペーンデータから実際に定期預金申込に至るかどうかを予測するモデルを構築する。
2.データセット
使用するデータは、27,128名の顧客データとキャンペーンの結果(定期預金申込の有無)データ。
最終的にコンペで予測するのは、18,083名のキャンペーンに対する反応(結果)。
データの確認
print(train.head(20)) #先頭20行の表示
・カラムの確認
print(train.columns) #カラムの表示
・要約統計量を確認する
print(train.describe()) #要約統計量の表示
・pandas_profilingで分析
import pandas_profiling as pdp pdp.ProfileReport(train) #pandas_profilingライブラリで分析
👉VisualStudioCodeだと見づらい。。。
🔹JupyterLabで開くと見やすくなる。
👉変数ごとのValueの割合など見やすく分析できる。
👉負値や欠損の有無もわかる。
🔹jobとyとの関係性について
train["y"] = (train["y"] == "yes").astype(np.int) print(train.groupby(["job"]).agg(["count","mean"])["y"])
🔹pythonでデータフレームの型を確認する
print(train.dtypes)
・せっかくなので図示もしてみる。
train["job"].value_counts.plot(kind = "bar")
👉棒グラフ
🔹データフレーム全体に対してヒストグラム を作成する
train.hist(); plt.tight_layout() #グラフを分ける plt.show()
🔹続いて散布図
plt.scatter(train["job"],train["y"])
👉x軸がjobのvalue値、y軸がy(yes,no)なので散布図だとあまり旨味はない。。
🔹散布図っぽいグラフにするため数値データ同士でプロットする。
plt.scatter(x=train["duration", y=train["balance"]])
3.前処理
続けてデータの前処理を実施する。
目的変数y(yes, no)をastype(np.int)でダミー変数にする
train["y"] = (train["y"] == "yes").astype(np.int)
・負値補正
print(train.describe()) train["pdays"] = train["pdays"].replace(-1,0) print(train.describe())
🔹年齢、資産をレンジに。
train["age_range"] = 1 train.col[train["age"] < 20, "age_range"] = 1 train.col[(train["age"] >= 20) & (train["age"] < 30), "age_range"] = 2 train.col[(train["age"] >= 30) & (train["age"] < 40), "age_range"] = 3 train.col[(train["age"] >= 40) & (train["age"] < 50), "age_range"] = 4 train.col[(train["age"] >= 50) & (train["age"] < 60), "age_range"] = 5 train.col[(train["age"] >= 60) & (train["age"] < 70), "age_range"] = 6 train.col[(train["age"] >= 70) & (train["age"] < 80), "age_range"] = 7 train.col[(train["age"] >= 80) & (train["age"] < 90), "age_range"] = 8 train.col[train["age"] >= 90, "age_range"] = 9
🔹balanceのヒストグラム
plt.hist(train["balance"])
データに偏りがあると単純にヒストグラム を出しても傾向が見えづらい。
👉表示範囲を指定する
plt.hist(train["balance"], range=(100,5000), bins=20) #range=(xx,xx)範囲指定、bins=x棒の数を指定
👉だいぶ見やすくなりました
🔹資産のレンジ
train["balance_range"] = 1 train.loc[train["balance"] < 0, "balance_range"] = 0 train.loc[(train["balance"] >= 0) & (train["balance"] < 10), "balance_range"] = 1 train.loc[(train["balance"] >= 10) & (train["balance"] < 100), "balance_range"] = 2 train.loc[(train["balance"] >= 100) & (train["balance"] < 250), "balance_range"] = 3 train.loc[(train["balance"] >= 250) & (train["balance"] < 450), "balance_range"] = 4 train.loc[(train["balance"] >= 450) & (train["balance"] < 700), "balance_range"] = 5 train.loc[(train["balance"] >= 700) & (train["balance"] < 1200), "balance_range"] = 6 train.loc[(train["balance"] >= 1200) & (train["balance"] < 2000), "balance_range"] = 7 train.loc[(train["balance"] >= 2000) & (train["balance"] < 3500), "balance_range"] = 8 train.loc[train["balance"] >= 3500, "balance_range"] = 9 print(train["balance_range"].value_counts(sort=False)) plt.hist(train["balance_range"])
👉うまくバラけさせることができました
🔹dayのレンジ
train["day_range"] = 1 train.loc[train["day"] <= 10, "day_range"] = 1 train.loc[(train["day"] > 10) & (train["day"] <= 20), "day_range"] = 2 train.loc[train["day"] > 20, "day_range"] = 3 print(train["day_range"].value_counts(sort=False))
・月の上旬、中旬、下旬
print(train.groupby(["day_range"]).agg(["count","mean"])["y"]) print(train.groupby(["month"]).agg(["count","mean"])["y"].sort_values("mean",ascending=False))
train["month_BME"] = 1 train.loc[(train["month"] == "jan") & (train["day_range"] == 1), "month_BME"] = 3 train.loc[(train["month"] == "jan") & (train["day_range"] == 2), "month_BME"] = 2 train.loc[(train["month"] == "jan") & (train["day_range"] == 3), "month_BME"] = 1 〜〜 train.loc[(train["month"] == "oct") & (train["day_range"] == 1), "month_BME"] = 36 train.loc[(train["month"] == "oct") & (train["day_range"] == 2), "month_BME"] = 35 train.loc[(train["month"] == "oct") & (train["day_range"] == 3), "month_BME"] = 34 print(train.groupby(["month_BME"]).agg(["count","mean"])["y"].sort_values("mean"))
前処理まで完了したのでモデルを構築して実際に予測します。
長くなったので別記事で。
ー
以上