累計

  • 156,636 pv

アクセスカウンター

機械学習 プログラミング

【機械学習】【R】Rでのデータ分析(2) ー銀行の顧客ターゲティング【SIGNATE】ー

2020-04-19

 

どうも、solobochiのbochiです。

 

昨年、データサイエンティスト協会主催のデータサイエンティスト養成講座を受講し、その中でRを使ったデータ分析手法を学んだのでその復習兼ねてまとめておきます。

前回記事↓の続きです。

 

【機械学習】【R】Rでのデータ分析(1) ー銀行の顧客ターゲティング【SIGNATE】ー

 

 

 



 

 

目次

    1. 概要(※前回記事参照)
    2. データセット(※前回記事参照)
    3. データ分析(※前回記事参照)
    4. 前処理
    5. モデル構築(※別記事参照)
    6. 改善(※別記事参照)
    7. 評価(※別記事参照)

 

 

 

4.前処理

データ分析で最も労力を割く部分であり、データ分析の90%ともいわれるデータの前処理。

具体的には、以下のような作業。

・欠損(システム的な欠損(N/A)だけでなく業務的な欠損(unknownや一律0など)も含む)

・負値

・重複

・変数の加工(※型変換、10倍、1/10倍、平均を取るなどして使いやすい形に加工する)

・変数の作成(※閾値を設けてダミー変数もしくは数値データに変換、パーセンタイル点を境にダミー変数化など)

・変数の作成(※複数条件を設定して条件に合致するか否かでダミー変数化、カテゴリ変数の文字列先頭に応じて数値データ化など)

・ダミー変数化(カテゴリ変数に対して使用して、そのvalueの分だけダミー変数の列を自動的に作成する)

 

 

まず欠損について確認。

table(is.na(train_data))

👉N/AがあればTRUEの件数が表示されるため、今回はN/Aはないことがわかる

 

N/Aではなく、unknownのデータがどの列に存在するかを確認する。

table(is.na(train_data))

👉3列目:job、5列目:education、10列目:contact、17列目:poutcomeにunknownのデータがあることがわかる

 

具体的には、

・job

 

education

 

contact

👉特に有用そうでもなく全体の25%ほどが欠損なのでこのカラムは使わない

 

・poutcome

👉全体の80%近くが欠損のためこのカラムは使わないとするか、successだった時の成約率の高さに注目してsuccessかどうかのダミー変数に加工して使うかはトライアンドエラーで。

 



 

 

 

続いて負値補正。

summary(train_data)

使ったコマンド

summary
使用目的:基本統計量の取得
使用方法:summary(dataframe)

 

👉pdaysに負値が存在するので補正する。

 

train_data_pre2$pdays[train_data_pre2$pdays < 0] <- 0

summary(train_data)
summary(train_data_pre2)

👉pdaysの負値を補完

 

 

次に、分析しやすいように変数を加工する。

・age

train_data_pre2$age_range <- trunc(train_data_pre2$age/10)*10

train_g2 <- dplyr::group_by(train_data_pre2,age_range)
dplyr::summarise(train_g2,n=n(),mean=mean(y))
train_g2

age_range

👉若年層と高齢層で成約率が高そう

使ったコマンド

summarise
使用目的:統計量を算出する、事前にgroupbyでグループ化しておくとグループごとの集計で算出できる
使用方法:dplyr::summarise(dataframe, xxx(mean,min,max,median))

 

・balance

train_data_pre2 <- train_data_pre2 %>%
  dplyr::mutate(balance_range = ifelse(balance<0,0, 
                                       ifelse(balance<100,1,
                                              ifelse(balance<200,2,
                                                     ifelse(balance<500,3,
                                                            ifelse(balance<1000,4,
                                                                   ifelse(balance<2000,5,
                                                                          ifelse(balance<5000,6,7))))))))

👉保有資産について、0、100、200、500、1000、2000、5000を閾値としてラベリング。

👉資産が増加するほど成約率も上がっていて正の相関が見られる。

👉グルーピングしてラベリングすることで、少数の特異値による影響を抑えることができて傾向が掴めるようになる。データ数が限定的な場合に有効な手法。

 

・day

train_data_pre2$day_range = ifelse(train_data_pre2$day<11,1,
                                   ifelse(train_data_pre2$day<21,2,3))

select(.data=train_data_pre2,day,day_range)

train_g2 <- dplyr::group_by(train_data_pre2,day_range)
dplyr::summarise(train_g2,n=n(),mean=mean(y))
train_g2

👉上旬(1日〜10日)、中旬(11日〜19日)、下旬(20日〜31日)にラベリング。

使ったコマンド

select
使用目的:データフレームの列を抽出する
使用方法:dplyr::summarise(dataframe, xxx(mean,min,max,median))

 

・month

train_data_pre2 <- train_data_pre2 %>%
  dplyr::mutate(month_label = ifelse(month=="jan",1,
                                     ifelse(month=="feb",2,
                                            ifelse(month=="mar",3,
                                                   ifelse(month=="apr",4,
                                                          ifelse(month=="may",5,
                                                                 ifelse(month=="jun",6,
                                                                        ifelse(month=="jul",7,
                                                                               ifelse(month=="aug",8,
                                                                                      ifelse(month=="sep",9,
                                                                                             ifelse(month=="oct",10,
                                                                                                    ifelse(month=="nov",11,
                                                                                                           ifelse(month=="dec",12,0)))))))))))))


train_g2 <- dplyr::group_by(train_data_pre2,month_label) 
dplyr::summarise(train_g2,n=n(),mean=mean(y))

👉7月、8月に比べて3月、4月、9月、10月の方が成約率が高い傾向にある

成約率でソートした結果がこちら↓

 

そこで、各月の上旬、中旬、下旬を表す変数を作成します。

train_data_pre2 <- train_data_pre2
train_data_pre2$month_BME = ifelse(train_data_pre2$month_label==3 && train_data_pre2$day_range==1,1,
                             ifelse(train_data_pre2$month_label==3 && train_data_pre2$day_range==2,2,
                              ifelse(train_data_pre2$month_label==3 && train_data_pre2$day_range==3,3,
                               ifelse(train_data_pre2$month_label==12 && train_data_pre2$day_range==1,4,
                                ifelse(train_data_pre2$month_label==12 && train_data_pre2$day_range==2,5,
                                 ifelse(train_data_pre2$month_label==12 && train_data_pre2$day_range==3,6,
                                  ifelse(train_data_pre2$month_label==9 && train_data_pre2$day_range==1,7,
                                   ifelse(train_data_pre2$month_label==9 && train_data_pre2$day_range==2,8,
                                    ifelse(train_data_pre2$month_label==9 && train_data_pre2$day_range==3,9,
                                     ifelse(train_data_pre2$month_label==10 && train_data_pre2$day_range==1,10,
                                      ifelse(train_data_pre2$month_label==10 && train_data_pre2$day_range==2,11,
                                        ifelse(train_data_pre2$month_label==10 && train_data_pre2$day_range==3,12,
                                          ifelse(train_data_pre2$month_label==4 && train_data_pre2$day_range==1,13,
                                            ifelse(train_data_pre2$month_label==4 && train_data_pre2$day_range==2,14,
                                              ifelse(train_data_pre2$month_label==4 && train_data_pre2$day_range==3,15,
                                                ifelse(train_data_pre2$month_label==2 && train_data_pre2$day_range==1,16,
                                                  ifelse(train_data_pre2$month_label==2 && train_data_pre2$day_range==2,17,
                                                    ifelse(train_data_pre2$month_label==2 && train_data_pre2$day_range==3,18,
                                                     ifelse(train_data_pre2$month_label==8 && train_data_pre2$day_range==1,19,
                                                      ifelse(train_data_pre2$month_label==8 && train_data_pre2$day_range==2,20,
                                                        ifelse(train_data_pre2$month_label==8 && train_data_pre2$day_range==3,21,
                                                          ifelse(train_data_pre2$month_label==6 && train_data_pre2$day_range==1,22,
                                                           ifelse(train_data_pre2$month_label==6 && train_data_pre2$day_range==2,23,
                                                            ifelse(train_data_pre2$month_label==6 && train_data_pre2$day_range==3,24,
                                                              ifelse(train_data_pre2$month_label==11 && train_data_pre2$day_range==1,25,
                                                                ifelse(train_data_pre2$month_label==11 && train_data_pre2$day_range==2,26,
                                                                  ifelse(train_data_pre2$month_label==11 && train_data_pre2$day_range==3,27,
                                                                    ifelse(train_data_pre2$month_label==1 && train_data_pre2$day_range==1,28,
                                                                      ifelse(train_data_pre2$month_label==1 && train_data_pre2$day_range==2,29,
                                                                        ifelse(train_data_pre2$month_label==1 && train_data_pre2$day_range==3,30,
                                                                          ifelse(train_data_pre2$month_label==7 && train_data_pre2$day_range==1,31,
                                                                            ifelse(train_data_pre2$month_label==7 && train_data_pre2$day_range==2,32,
                                                                              ifelse(train_data_pre2$month_label==7 && train_data_pre2$day_range==3,33,
                                                                                ifelse(train_data_pre2$month_label==5 && train_data_pre2$day_range==1,34,
                                                                                  ifelse(train_data_pre2$month_label==5 && train_data_pre2$day_range==2,35,
                                                                                    ifelse(train_data_pre2$month_label==5 && train_data_pre2$day_range==3,36,0))))))))))))))))))))))))))))))))))))

colnames(train_data_pre2)

 



 

 

 

変数加工の続き、カテゴリ変数のダミー変数化。

 

train_data_ohe2 <- train_data_pre2
train_data_ohe2 <- dummies::dummy.data.frame(train_data_pre2,sep="_",names = c("job","marital","education","default","housing","loan"))

str(train_data_ohe2)

👉カテゴリ変数がダミー変数化された。

使ったコマンド

select
使用目的:データフレームの列を抽出する
使用方法:select(dataframe,xxx(変数))

使用目的:データフレームの列を削除する(データフレームの特定の列以外を抽出)
使用方法:select(-c(xxx(変数),xxx(変数),,,))

dummies::dummy.data.frame
使用目的:カテゴリ変数をダミー変数化する

使用方法:dummies::dummy.data.frame(dataframe , sep = "_" , names = c("xxx(変数)","xxx(変数)",,,) )

 

 

このあと機械学習アルゴリズムを用いてのモデル構築、評価と続く。

また少し長くなったので続きは別記事で。

 

 

 

 

 

 

以上

 

 

 

 

 

  • この記事を書いた人
  • 最新記事

solobochi

(名前):solobochi

(説明)
独身アラサー男子
国内大手IT企業中堅社員。
プログラミングやセミナーのアウトプットがしたいと思いブログを開設。
プロジェクトマネジメント関連の資格やディープラーニング、機械学習系の資格取得ノウハウについても発信。


(Like)
・最適化することが好き
・PDCAを回すのが好き


(当サイト)
日々思うことを徒然と発信
└(例)
・学びのアウトプット
・投資・資産運用
・プログラミング
・資格試験の対策
・セミナーのレビュー
・書評
etc...


詳しくは自己紹介記事にて。
自己紹介①
自己紹介②
自己紹介③
自己紹介④

-機械学習, プログラミング
-, , ,

Copyright© そろボチ , 2023 All Rights Reserved Powered by AFFINGER5.