【第1回】Python Marketing Data Analytics! ~古典的マーケティングデータ分析にも目を向けて~
このカテゴリは本業、データ分析系のお話やTipsです。
Qiitaに書くレベルではない自分の覚書や練習記録、情報提供として残していこうかと。
1年後に「まだ自分はこの程度だったのか~wクソダサいww」というのが目標です。
つーかブログ趣旨とギャップありすぎて、別ブログ立ち上げるべきかと思いましたが、
まあゆるくやっていけばいいや、というめんどくさい精神全開の結果です。ご容赦ください。
モチベーション
なんでこんなタイトルにしたかというと、
機械学習・ディープラーニングが全盛の中、もうちょっとPythonでの古典的な統計解析、データ分析手法中心のネタがあってもいいんじゃね?
と思ったから。
というか、僕自身が勉強しないと、基礎が全くダメだなぁと思ったからです。
Pythonで機械学習・ディープラーニングによる予測精度向上が全盛だけど、ScipyやStatsmodelsを中心に、モデル推定や効果検証とかも勉強しないとだめだなぁ。
— H.Kobayashi (@h_kobayashi1125) 2018年4月17日
まぁ、Python自体が統計解析ライブラリがRほど充実していないので、当然といれば当然ですが・・・。
ビッグデータと呼ばれる大量データの分析が中心の今、データ分析は推測統計や検定はだいぶ意気消沈していそうな気がします。
(機械学習系の情報がWebに溢れかえっているせいかもしれませんが・・・)
でも世間にはきっと、
データは少ないけど、そこから得られるものを導き出したい。
予測ではなくて、目的変数に与える影響要因の分析がしたい。
とか、そういうニーズも多いはず。
いわゆるAIでの予測ではなく、BI(ビジネスインテリジェンス)の視点でデータからインサイトを得よう!という趣旨のデータ分析ですね。
ということで、勉強がてら、「マーケティング」をネタにしたPythonデータ分析記事を色々書いていこうと思います。
もちろん、機械学習の技術なども入ってくると思いますが。
なお、内容には誤りなどがある可能性がありますので、ご容赦ください。
ぼくの勉強不足&不手際です。精進します。
お気づきの際はご指摘いただけると喜びます。
実行環境について
以下の記事を参照ください。
Kaggleのデータは使わないと思いますが、Colaboratory(Python3)を使ってます。
利用データについて
しばらくは、UCI Machine Learning RepositoryのBank Marketing Data Set を利用していきます。
利用するデータはbank.csv
です。
では、以下からスタート!長く続くといいなぁw
必要ライブラリのインポート
import numpy as np import pandas as pd from scipy import stats import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline
データの読み込み
pd.set_option("display.max_columns", 50) df = pd.read_table('bank.csv', sep=';') df.head()
age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 30 | unemployed | married | primary | no | 1787 | no | no | cellular | 19 | oct | 79 | 1 | -1 | 0 | unknown | no |
1 | 33 | services | married | secondary | no | 4789 | yes | yes | cellular | 11 | may | 220 | 1 | 339 | 4 | failure | no |
2 | 35 | management | single | tertiary | no | 1350 | yes | no | cellular | 16 | apr | 185 | 1 | 330 | 1 | failure | no |
3 | 30 | management | married | tertiary | no | 1476 | yes | yes | unknown | 3 | jun | 199 | 4 | -1 | 0 | unknown | no |
4 | 59 | blue-collar | married | secondary | no | 0 | yes | no | unknown | 5 | may | 226 | 1 | -1 | 0 | unknown | no |
データの概要を把握する
データ分析の第1歩は、そのデータの概要を掌握することからスタートしよう。
とくに、データに対するドメイン知識が無い場合、単なる記述統計からでもデータの背景にある事象の概況は推察できる。
df.shape
(4521, 17)
このデータは、4,521レコード、17カラムで構成されていることが分かる。
つまり、4,521人分のデータであり、1人あたり17の変数となるデータを持っていることになる。
df.columns
Index(['age', 'job', 'marital', 'education', 'default', 'balance', 'housing',
'loan', 'contact', 'day', 'month', 'duration', 'campaign', 'pdays',
'previous', 'poutcome', 'y'],
dtype='object')
各カラムの名前は上記コードで取得できる。 このデータセットは、ポルトガルの銀行機関のダイレクトマーケティングの実績データのようだ。
このデータセットを持ってきたUCI Machine Learning Repositoryから、データセットの変数の内容を拝借すると、以下のとおりとなっている。
変数名 | 内容 |
---|---|
age | 年齢 |
job | 仕事 |
marital | 婚姻有無 |
education | 教育水準 |
default | クレジットカードの債務不履行有無 |
balance | 年間平均残高(€) |
housing | j住宅ローンの有無 |
loan | 個人ローンの有無 |
contact | 連絡方法 |
day | 最終接触日 |
month | 最終接触月 |
duration | 最終接触時間(秒) |
campaign | キャンペーン中の連絡数 |
pdays | 最後に連絡した日からの日数 |
previous | キャンペーンまでに接触した回数 |
poutcome | 以前のマーケティングキャンペーンの結果 |
y | 定期預金の契約有無 |
※ちなみに、このデータを題材にSIGNEATEでオープンコンペが開かれている。
まず、それぞれのカラムとデータ型を確認する。
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4521 entries, 0 to 4520
Data columns (total 17 columns):
age 4521 non-null int64
job 4521 non-null object
marital 4521 non-null object
education 4521 non-null object
default 4521 non-null object
balance 4521 non-null int64
housing 4521 non-null object
loan 4521 non-null object
contact 4521 non-null object
day 4521 non-null int64
month 4521 non-null object
duration 4521 non-null int64
campaign 4521 non-null int64
pdays 4521 non-null int64
previous 4521 non-null int64
poutcome 4521 non-null object
y 4521 non-null object
dtypes: int64(7), object(10)
memory usage: 600.5+ KB
int64の数値型が7カラム、objectが10カラムあることが分かる。 次に、各カラムの基本統計量を確認する。
df.describe()
age | balance | day | duration | campaign | pdays | previous | |
---|---|---|---|---|---|---|---|
count | 4521.000000 | 4521.000000 | 4521.000000 | 4521.000000 | 4521.000000 | 4521.000000 | 4521.000000 |
mean | 41.170095 | 1422.657819 | 15.915284 | 263.961292 | 2.793630 | 39.766645 | 0.542579 |
std | 10.576211 | 3009.638142 | 8.247667 | 259.856633 | 3.109807 | 100.121124 | 1.693562 |
min | 19.000000 | -3313.000000 | 1.000000 | 4.000000 | 1.000000 | -1.000000 | 0.000000 |
25% | 33.000000 | 69.000000 | 9.000000 | 104.000000 | 1.000000 | -1.000000 | 0.000000 |
50% | 39.000000 | 444.000000 | 16.000000 | 185.000000 | 2.000000 | -1.000000 | 0.000000 |
75% | 49.000000 | 1480.000000 | 21.000000 | 329.000000 | 3.000000 | -1.000000 | 0.000000 |
max | 87.000000 | 71188.000000 | 31.000000 | 3025.000000 | 50.000000 | 871.000000 | 25.000000 |
まずは数値型のデータ確認。それぞれの用語は以下のとおりである。
項目 | 意味 |
---|---|
count | データ数 |
mean | 算術平均 |
std | 標準偏差 |
min | 最小値 |
25% | 25パーセンタイル |
50% | 50パーセンタイル(中央値) |
75% | 75パーセンタイル |
max | 最大値 |
オブジェクトのカラムの概要も以下で算出できる。
df.describe(include='O') # 大文字の「O(オー)」(Object)をincludeで指定すればオブジェクトのカラムを取得できる。
job | marital | education | default | housing | loan | contact | month | poutcome | y | |
---|---|---|---|---|---|---|---|---|---|---|
count | 4521 | 4521 | 4521 | 4521 | 4521 | 4521 | 4521 | 4521 | 4521 | 4521 |
unique | 12 | 3 | 4 | 2 | 2 | 2 | 3 | 12 | 4 | 2 |
top | management | married | secondary | no | yes | no | cellular | may | unknown | no |
freq | 969 | 2797 | 2306 | 4445 | 2559 | 3830 | 2896 | 1398 | 3705 | 4000 |
それぞれ用語は以下のとおり。
項目 | 意味 |
---|---|
count | データ数 |
unique | 変数の種類数 |
top | 最頻値 |
freq | 最頻値の頻度 |
pandas.DataFrame.describe
だけでもいろいろなことが分かりそうだ。
例えばbalance
に着目してみると、平均値と中央値(50%値)の値が大きく乖離しており、 平均値 > 中央値 となっている。
これは例えば年収分布と同じ減少で、少数の値が大きいデータやはずれ値に平均値が引き上げられている可能性を示す。
つまり、右に裾が長い分布となっていることが推察できる。
なお、pandas.DataFrame.describe
では数値、オブジェクトすべて一括して表示することも可能である。
df.describe(include='all')
age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 4521.000000 | 4521 | 4521 | 4521 | 4521 | 4521.000000 | 4521 | 4521 | 4521 | 4521.000000 | 4521 | 4521.000000 | 4521.000000 | 4521.000000 | 4521.000000 | 4521 | 4521 |
unique | NaN | 12 | 3 | 4 | 2 | NaN | 2 | 2 | 3 | NaN | 12 | NaN | NaN | NaN | NaN | 4 | 2 |
top | NaN | management | married | secondary | no | NaN | yes | no | cellular | NaN | may | NaN | NaN | NaN | NaN | unknown | no |
freq | NaN | 969 | 2797 | 2306 | 4445 | NaN | 2559 | 3830 | 2896 | NaN | 1398 | NaN | NaN | NaN | NaN | 3705 | 4000 |
mean | 41.170095 | NaN | NaN | NaN | NaN | 1422.657819 | NaN | NaN | NaN | 15.915284 | NaN | 263.961292 | 2.793630 | 39.766645 | 0.542579 | NaN | NaN |
std | 10.576211 | NaN | NaN | NaN | NaN | 3009.638142 | NaN | NaN | NaN | 8.247667 | NaN | 259.856633 | 3.109807 | 100.121124 | 1.693562 | NaN | NaN |
min | 19.000000 | NaN | NaN | NaN | NaN | -3313.000000 | NaN | NaN | NaN | 1.000000 | NaN | 4.000000 | 1.000000 | -1.000000 | 0.000000 | NaN | NaN |
25% | 33.000000 | NaN | NaN | NaN | NaN | 69.000000 | NaN | NaN | NaN | 9.000000 | NaN | 104.000000 | 1.000000 | -1.000000 | 0.000000 | NaN | NaN |
50% | 39.000000 | NaN | NaN | NaN | NaN | 444.000000 | NaN | NaN | NaN | 16.000000 | NaN | 185.000000 | 2.000000 | -1.000000 | 0.000000 | NaN | NaN |
75% | 49.000000 | NaN | NaN | NaN | NaN | 1480.000000 | NaN | NaN | NaN | 21.000000 | NaN | 329.000000 | 3.000000 | -1.000000 | 0.000000 | NaN | NaN |
max | 87.000000 | NaN | NaN | NaN | NaN | 71188.000000 | NaN | NaN | NaN | 31.000000 | NaN | 3025.000000 | 50.000000 | 871.000000 | 25.000000 | NaN | NaN |
このような記述統計からデータの概要を把握していくことが第一歩となる。
つぎに、推察した内容が的確かどうか、データの可視化などを進めて確認していく。
つづく
とりあえず今回はここまで。 次回はmatplotlibやseabornを使ってデータの可視化を行っていきます。
考察
Colaboratory上の.ipynb
を.md
にしてブログに上げるのがクソめんどくさいことが分かったので、
今後どうするか模索。
普通にjupyterでやるべきなのか・・・。GitHubを使うのも良さそう。