本資料はOBS授業「ビジネスデータ分析」の第7回授業「顧客管理のためのデータ分析」を補足するものです。使用しているサンプルデータファイル“RFM.csv”は照井伸彦・佐藤忠彦『現代マーケティングリサーチ』所載のデータです。但し、分析作業は原著者とは関係なく、西山が行ったことをお断りしておきます。

最初にデータファイル“RFM.csv”が保存されているフォルダーを作業用ディレクトリーにしておきます(「作業用ディレクトリー」の意味が分からない場合は、Rの利用法を先に勉強して下さい。授業を履修している方はMANABAにRへのガイドブックを提供しています。

dir()
## [1] "RFM.csv"                        "RFMAnalysis-OBS-Appendix.html" 
## [3] "RFMAnalysis-OBS-Appendix.ipynb" "RFMAnalysis-OBS-Appendix.rmd"  
## [5] "rsconnect"

データファイルはCSVファイルですから以下のように読み込みます。

rfm <- read.csv(file="RFM.csv")

デーファイルを読み込んだ後、まずは要約して大雑把にデータの中身をみておくが鉄則です。

dim(rfm)
## [1] 2000    5
summary(rfm)
##     Customer            M                F               R         
##  Min.   :   1.0   Min.   :   467   Min.   : 1.00   Min.   :  1.00  
##  1st Qu.: 500.8   1st Qu.:141747   1st Qu.: 6.00   1st Qu.: 20.75  
##  Median :1000.5   Median :274411   Median :12.00   Median : 41.00  
##  Mean   :1000.5   Mean   :276496   Mean   :12.81   Mean   : 55.22  
##  3rd Qu.:1500.2   3rd Qu.:418265   3rd Qu.:18.00   3rd Qu.: 74.00  
##  Max.   :2000.0   Max.   :549795   Max.   :40.00   Max.   :229.00  
##    DM      
##  no :1279  
##  yes: 721  
##            
##            
##            
## 

数量データR, F, Mについてはヒストグラムもみておく。これを習慣づけましょう。

par(mfrow=c(1,3)) # 横に3つの図を並べる
hist(rfm$F)
hist(rfm$M)
hist(rfm$R)

5分位分析(デシル分析の簡単版)

変数R, F, Mはそれぞれ「直近来店時からの経過日数」、「累積来店回数」、「累積購買金額」であり、CRMのための基本三因子として活用されるようになってきています。まずはシンプルなデータ活用法である10分位分析(デシル分析)、但しこの資料ではレコード数が2000人と比較的少数のため5分位分析を行ってみることにします。

それには、F,M,Rそれぞれを大小順に並べてから、同じ人数ずつ5つのクラスにわけます。2000人を400人ずつ5つのクラスに分けたうえ、クラスには“F1”から“F5”、“M1”から“M5”、“R1”から“R5”のように名前をつけることにします。元の数量データをその大きさに従って区分し、クラスに名前をつけるわけですから行うことは数値から分類カテゴリーへの変換です。そのためこのような作業をカテゴリー化と言います。

カテゴリー化には“cut”コマンドを使います。クラス名を値とする新たな質的変数は分類のための因子(=ファクター)になります。

まずデータ“F”を区分して、小さい順に“F1”, “F2”, “F3”, “F4”, “F5”とクラス名をつけます。

qt <- quantile(rfm$F, probs = c(0,0.2,0.4,0.6,0.8,1))
rankF <- cut(rfm$F, breaks = qt, labels = c("F1", "F2", "F3", "F4", "F5"), include.lowest = TRUE)

新しい質的変数“rankF”を作りましたから、その内容をみておきましょう。

class(rankF) # 変数の型を調べる
## [1] "factor"
length(rankF) # 含まれている値の数を確認。2000人分。
## [1] 2000
rfm$F[1:20] # 元の数量の値
##  [1]  6  4 15 30 12  4  6 15  4 13 19 24 17 25  3  3 11  8 14 24
rankF[1:20] # その数量をカテゴリー化した後のクラス名
##  [1] F2 F1 F4 F5 F3 F1 F2 F4 F1 F3 F4 F5 F4 F5 F1 F1 F3 F2 F3 F5
## Levels: F1 F2 F3 F4 F5
table(rankF) # 分布。理屈としては400名ずつのクラスになるはず
## rankF
##  F1  F2  F3  F4  F5 
## 496 334 389 436 345

同じ値は同じクラスに入るため、値が小数ではなく、整数で値が重複する人が多い場合は、正確に400人ずつのクラスにはなりません。とはいえ、分析に困ることはありません。下の、累積購買金額は1円単位で値が入力されているということもあって、400人ずつのクラスができました。

qt <- quantile(rfm$M, probs = c(0,0.2,0.4,0.6,0.8,1))
rankM <- cut(rfm$M, breaks = qt, labels = c("M1", "M2", "M3", "M4", "M5"), include.lowest = TRUE)
length(rankM)
## [1] 2000
table(rankM)
## rankM
##  M1  M2  M3  M4  M5 
## 400 400 400 400 400

最後の「直近来店時からの経過日数」は多少工夫をします。経過日数は短いほど良いわけですから、最も短いクラスを高評価の“R5”という名前とし、経過日数が増えるにしたがって“R4”, “R3”, “R2”, “R1”のようにクラス名をつけることにしましょう(そうしなければならないわけではありません)。

qt <- quantile(rfm$R, probs = c(0,0.2,0.4,0.6,0.8,1))
rankR <- cut(rfm$R, breaks = qt, labels = c("R5", "R4", "R3", "R2", "R1"), include.lowest = TRUE)
length(rankR)
## [1] 2000
table(rankR)
## rankR
##  R5  R4  R3  R2  R1 
## 400 419 387 395 399

箱ひげ図の作成

各数量変数について5分位クラス名をせっかく付けましたから、それを活用して箱ひげ図を描いてみましょう。

まずはグラフ作成の定番パッケージになっている“ggplot2”をロードします(もしここでエラーが出れば、“ggplot2”インストールしてください)。

library(ggplot2)

累積来店回数(F)の箱ひげ図をrankFで層別化して作成すると、以下のようになります。クラスが最下位の“F1”からより上位のクラスへ移るごとに来店回数が増えていることが再確認できます。

ggplot(rfm, aes(x=rankF, y=F)) + geom_boxplot()

累積購買金額(M)、直近来店時からの経過日数(R)も同様です。

ggplot(rfm, aes(x=rankM, y=M)) + geom_boxplot()

経過日数(R)についても箱ひげ図が理屈にかなっているかをチェックしておきましょう。直近来店時からの経過日数(R)については最も経過日数が少ないクラスを高く評価して“R5”としている点に注意してください。

ggplot(rfm, aes(x=rankR, y=R)) + geom_boxplot()

Rコマンダーでは数値変数を区分したときのクラス名は自動的に同じデータセットに追加されましたが、コマンドで操作しているときは、新しく作った変数が自動的にどこかに追加されることはありません。Rコマンダーで「データセット」というのは、実は「データフレーム(data.frame)」と呼ばれるタイプの変数ですが、データフレームに新しくデータを追加するときは以下のようにします。

rfm <- data.frame(rfm, rankF, rankM, rankR) # 同じ長さ(行数)の表やデータを一つにまとめる
class(rfm)
## [1] "data.frame"
head(rfm) # 最初の何行かをみたいときは"head"コマンドを使う
##   Customer      M  F   R  DM rankF rankM rankR
## 1        1 311349  6   6 yes    F2    M3    R5
## 2        2 509794  4  28 yes    F1    M5    R4
## 3        3 176331 15  51 yes    F4    M2    R2
## 4        4 402413 30  33 yes    F5    M4    R3
## 5        5  16689 12   4  no    F3    M1    R5
## 6        6 263978  4 126  no    F1    M3    R1

来店回数と購買金額で優良顧客を選び出す

累積来店回数の上位クラス“F5”, “F4”だけを取り出しましょう。

goodF <- subset(rfm, subset = (rankF=="F5"|rankF=="F4")) # 行や列を取り出すときはエクセルよりRのほうが遥かに効率的
dim(goodF)
## [1] 781   8
head(goodF,10)
##    Customer      M  F  R  DM rankF rankM rankR
## 3         3 176331 15 51 yes    F4    M2    R2
## 4         4 402413 30 33 yes    F5    M4    R3
## 8         8 125001 15 35  no    F4    M2    R3
## 11       11 219339 19 50 yes    F4    M2    R3
## 12       12 418277 24  4 yes    F5    M4    R5
## 13       13 191852 17 58 yes    F4    M2    R2
## 14       14 325230 25 20  no    F5    M3    R4
## 20       20 468018 24 46 yes    F5    M5    R3
## 23       23 312326 26  4 yes    F5    M3    R5
## 24       24 522631 34 25 yes    F5    M5    R4

これを更に累積購買金額で絞り込みます。

goodFM <- subset(goodF, subset = (rankM=="M5"|rankM=="M4")) # 来店回数(F)で上位層を取り出した後、購買金額(M)の上位層を抽出する
dim(goodFM)
## [1] 457   8
head(goodFM,10)
##    Customer      M  F  R  DM rankF rankM rankR
## 4         4 402413 30 33 yes    F5    M4    R3
## 12       12 418277 24  4 yes    F5    M4    R5
## 20       20 468018 24 46 yes    F5    M5    R3
## 24       24 522631 34 25 yes    F5    M5    R4
## 26       26 440905 20 34 yes    F4    M4    R3
## 27       27 515250 34 21 yes    F5    M5    R4
## 32       32 498366 23 13 yes    F5    M5    R5
## 35       35 495402 26 54  no    F5    M5    R2
## 43       43 547412 31 27 yes    F5    M5    R4
## 45       45 472860 22 23  no    F5    M5    R4

2回の絞り込みで457人を抽出することができました。ここでどんな顧客が選び出されたのか要約をしておきましょう。

summary(goodFM)
##     Customer            M                F               R        
##  Min.   :   4.0   Min.   :333292   Min.   :15.00   Min.   : 1.00  
##  1st Qu.: 512.0   1st Qu.:397427   1st Qu.:19.00   1st Qu.:14.00  
##  Median : 951.0   Median :452068   Median :24.00   Median :27.00  
##  Mean   : 998.3   Mean   :448627   Mean   :24.08   Mean   :27.95  
##  3rd Qu.:1490.0   3rd Qu.:504388   3rd Qu.:28.00   3rd Qu.:41.00  
##  Max.   :2000.0   Max.   :549795   Max.   :40.00   Max.   :60.00  
##    DM      rankF    rankM    rankR   
##  no :118   F1:  0   M1:  0   R5:132  
##  yes:339   F2:  0   M2:  0   R4:148  
##            F3:  0   M3:  0   R3:116  
##            F4:149   M4:211   R2: 61  
##            F5:308   M5:246   R1:  0  
## 

当然ながら、rankFについては“F1”, “F2”, “F3”が、またrankMについては“M1”, “M2”, “M3”が含まれていません。この段階で、前回のダイレクトメール(クーポン付き)に反応して来店した客の割合が\(339/(118+339)=0.74\)となり4人の内の3人がメールに反応したことが分かります。

ロジステッィク回帰分析で予測モデル―全データ

データの全体を使ってダイレクトメール(クーポン付き)への反応予測モデルを作る方が良いというのはその通りです。

model1 <- glm(DM ~ F + M + R, family=binomial(link="logit"), data=rfm)
summary(model1)
## 
## Call:
## glm(formula = DM ~ F + M + R, family = binomial(link = "logit"), 
##     data = rfm)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.5349  -0.7560  -0.3634   0.7937   2.7024  
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -2.193e+00  1.857e-01 -11.810  < 2e-16 ***
## F            9.488e-02  8.553e-03  11.093  < 2e-16 ***
## M            3.505e-06  3.900e-07   8.987  < 2e-16 ***
## R           -1.580e-02  2.014e-03  -7.845 4.32e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2614.8  on 1999  degrees of freedom
## Residual deviance: 1910.5  on 1996  degrees of freedom
## AIC: 1918.5
## 
## Number of Fisher Scoring iterations: 5
exp(model1$coefficients)
## (Intercept)           F           M           R 
##    0.111547    1.099526    1.000004    0.984324

ロジスティック回帰分析における「理論値(fitted.values)」は、それぞれの顧客がダイレクトメールに反応する確率です。これを元のデータセット“rfm”に追加しておきましょう。そのついでに、顧客全体の反応確率がどう分布しているかも見ておきましょう。

rfm$prob <- model1$fitted.values
summary(rfm$prob)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 0.003957 0.120302 0.308469 0.360500 0.570401 0.966078
ggplot(rfm, aes(x=prob)) + geom_line(stat="density")

反応確率の平均値は36%です。これはそもそも前回のダイレクトメールに反応した客の割合36%と符合しています。 ただ、反応確率の分布図をみると、10%未満の低い値に山があり、反応すると期待できそうな人は余り多くはないような印象をうけます。あまり得る所は多くはない図であるのが事実ですね(^^;;)

来店回数の階級(rankF)で層別化した分布図です。これをみると、来店回数の階級ごとに反応確率がハッキリと分離されている(=重なっている)ことが分かります。言葉を変えると、ダイレクトメールに反応して来店するかどうかに対して、それまでの累積来店回数の多寡がハッキリした効果をもっている、そんな理屈になります。もし来店回数とクーポンへの反応が無関係であれば、来店回数でクラス分けしても、クラスごとの反応確率の分布に影響はない、つまり分布図は重なっていなければなりません。

ggplot(rfm, aes(x=prob, color=rankF)) + geom_density()

ロジステッィク回帰分析の計算結果をみても、係数の大きさから察しはつくのですが、こうしてグラフに見える化する手法の方をおすすめしなす。

ggplot(rfm, aes(x=prob, color=rankM)) + geom_density()

積購買金額(M)も反応確率に影響することが上の図をみればわかります。それに対して、直近来店時から経過日数は、特に“R3”, “R4”, “R5”の分布図が重なっています。ということは、経過日数はクーポンへの反応にほとんど影響がないということです。ただ、”R1“クラスだけは来店する可能性がほとんどないことがハッキリしていいます。

ggplot(rfm, aes(x=prob, color=rankR)) + geom_density()

経過日数については、クラス“R1”に含まれるかどうかだけが重要だと言えそうです。

直近来店時からの経過日数で最も下位にある“R1”は、具体的にどの程度の日数がたっている客なのか?この点だけを一応確かめておきましょう。

summary(subset(rfm, rankR == "R1"))
##     Customer            M                F                R        
##  Min.   :   6.0   Min.   :   467   Min.   : 1.000   Min.   : 93.0  
##  1st Qu.: 477.0   1st Qu.: 89613   1st Qu.: 2.000   1st Qu.:107.0  
##  Median : 961.0   Median :196858   Median : 4.000   Median :124.0  
##  Mean   : 971.3   Mean   :221939   Mean   : 4.323   Mean   :138.3  
##  3rd Qu.:1482.5   3rd Qu.:336870   3rd Qu.: 6.000   3rd Qu.:169.0  
##  Max.   :1999.0   Max.   :549734   Max.   :10.000   Max.   :229.0  
##    DM      rankF    rankM    rankR         prob         
##  no :372   F1:287   M1:118   R5:  0   Min.   :0.003957  
##  yes: 27   F2: 91   M2:101   R4:  0   1st Qu.:0.021265  
##            F3: 21   M3: 78   R3:  0   Median :0.041787  
##            F4:  0   M4: 55   R2:  0   Mean   :0.054865  
##            F5:  0   M5: 47   R1:399   3rd Qu.:0.073996  
##                                       Max.   :0.250402

上のコマンドの意味は、データセット“rfm”からrankRの値が“R1”である行(=客)だけを抜き取り(subsetコマンド)、その後で要約をする(summaryコマンド)ものです。

これを見ると、経過日数が93日以上になっています(最大は229日経過)。前回のダイレクトメールにも反応していない客がほとんど大半を占めていることが分かります。要するに、最後に来てから3か月以上たっている顧客はダイレクトメールにまずは反応しない。そう予測してもよい。前回ダイレクトメールへの反応実績に基づく限り、こんな見込みがたちそうです。

ロジステッィク回帰分析で予測モデル―通常作業

顧客行動の予測モデルを作成する際には、通常、データ全体を推定に使用するトレーニングデータと予測能力の評価に使うテストデータの二つに分割しています。多くの場合、テスト用に使うデータ割合は10%を目安にしても問題はないと思われます。ここでは全データ2000人からランダムに200人をテスト用に留保し、残りの1800人を予測モデル作成に使うことにします。

テスト用のデータセットを抜き取る方法には複数のやり方がありますが、ここでは最も単純な方法、即ち1から2000までの整数を乱順に並べ替えたうえで、最初の200行をテスト用に、残りをトレーニング用のデータとします。それには“sample”コマンドが便利でしょう。例えば、1から10までの整数を並べ替えるには以下のようにします。

sample(1:10,10)
##  [1]  2  9  8  6  7  3  5  4 10  1

2000人の顧客をテスト用の200人とトレーニング用の1800人に分けましょう。

idx <- sample(1:2000, 2000) # 1から2000までを乱順に並べる
test.id <- idx[1:200] # 最初の200個を保存
train.id <- idx[201:2000] # 残りの1800個の数字を保存
test <- rfm[test.id, ] # データセット"rfm"からtest.idで保存された行番号をとりだす
train <- rfm[train.id, ] # 残りの1800行をとりだす

データ全体をスプリットした時点で、トレーニングデータとテストデータの要約を見ておきます。

以下に見るとおり、RFMの各種属性、反応確率、ダイレクトメールへの反応割合とも概ね同じになっているので、二つのグループの傾向は同じであると判定できます。

なお、どの顧客をテスト用にするかにはランダム性があります。したがって残りのトレーニング用1800名も必ずしも確定しているわけではなくサンプリングのたびに変わる余地があります。トレーニングデータを用いたロジスティック回帰分析の結果も本資料の数値とは僅かに異なるかもしれない点を念頭においてください。

dim(train)
## [1] 1800    9
summary(train)
##     Customer            M                F               R         
##  Min.   :   1.0   Min.   :   467   Min.   : 1.00   Min.   :  1.00  
##  1st Qu.: 501.8   1st Qu.:140687   1st Qu.: 6.00   1st Qu.: 21.00  
##  Median :1000.5   Median :278800   Median :12.00   Median : 40.00  
##  Mean   :1001.7   Mean   :276579   Mean   :12.92   Mean   : 54.66  
##  3rd Qu.:1498.2   3rd Qu.:416328   3rd Qu.:18.00   3rd Qu.: 71.00  
##  Max.   :1999.0   Max.   :549795   Max.   :40.00   Max.   :229.00  
##    DM       rankF    rankM    rankR         prob         
##  no :1147   F1:439   M1:367   R5:357   Min.   :0.003957  
##  yes: 653   F2:300   M2:341   R4:387   1st Qu.:0.124136  
##             F3:348   M3:368   R3:356   Median :0.312395  
##             F4:394   M4:369   R2:353   Mean   :0.363261  
##             F5:319   M5:355   R1:347   3rd Qu.:0.575063  
##                                        Max.   :0.966078
dim(test)
## [1] 200   9
summary(test)
##     Customer            M                F               R         
##  Min.   :  10.0   Min.   :  1692   Min.   : 1.00   Min.   :  1.00  
##  1st Qu.: 497.0   1st Qu.:148262   1st Qu.: 5.00   1st Qu.: 20.00  
##  Median :1001.0   Median :248755   Median :10.00   Median : 46.00  
##  Mean   : 989.4   Mean   :275754   Mean   :11.87   Mean   : 60.23  
##  3rd Qu.:1539.0   3rd Qu.:425731   3rd Qu.:17.00   3rd Qu.: 96.25  
##  Max.   :2000.0   Max.   :549370   Max.   :40.00   Max.   :226.00  
##    DM      rankF   rankM   rankR        prob         
##  no :132   F1:57   M1:33   R5:43   Min.   :0.006198  
##  yes: 68   F2:34   M2:59   R4:32   1st Qu.:0.091570  
##            F3:41   M3:32   R3:31   Median :0.281554  
##            F4:42   M4:31   R2:42   Mean   :0.335654  
##            F5:26   M5:45   R1:52   3rd Qu.:0.520197  
##                                    Max.   :0.960561

まずトレーニング用のデータで行動予測モデルを作成し、その予測モデルを計算には含めなかったテストデータに適用して結果を予測することにします。テストデータについても、実際の行動やYesかNoで分かっていますから、予測された行動と実際の行動を比べることによって予測精度を評価することができます。

model2 <- glm(DM ~ F + M + R, family=binomial(link="logit"), data=train)
summary(model2)
## 
## Call:
## glm(formula = DM ~ F + M + R, family = binomial(link = "logit"), 
##     data = train)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.3687  -0.7584  -0.3704   0.8018   2.6850  
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -2.216e+00  1.958e-01 -11.313  < 2e-16 ***
## F            9.498e-02  9.008e-03  10.545  < 2e-16 ***
## M            3.509e-06  4.125e-07   8.507  < 2e-16 ***
## R           -1.536e-02  2.128e-03  -7.220 5.21e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2358.0  on 1799  degrees of freedom
## Residual deviance: 1727.5  on 1796  degrees of freedom
## AIC: 1735.5
## 
## Number of Fisher Scoring iterations: 5
exp(model2$coefficients)
## (Intercept)           F           M           R 
##   0.1090909   1.0996419   1.0000035   0.9847563

(当然であるとも言えるのですが)上の結果“model1”と同様の結果が出ています。テストデータも概ね同じ傾向を示していますから、この予測モデルを適用しても問題はないはずです - ただし、テストデータに含まれる個々の顧客は上の予測モデル作成には使ってはいないことに注意してください。

予測モデルの評価

予測モデルがデータにどの程度フィットしているかをまず確認しておきましょう。

そのため、トレーニングデータについて説明変数から予測される行動と実際にとっていた行動とを比べることにします。この予測された行動とは予測モデルから計算される反応確率が0.5を超えると「反応する(Y)」、0.5未満なら「反応しない(N)」という行動予測のことです。

pred <- predict(model2, newdatda=train, type="response")
yn.yosoku <- ifelse(pred > 0.5, "Y", "N")
yn.yosoku <- as.factor(yn.yosoku)
tbl <- table(yn.yosoku, train$DM)
tbl
##          
## yn.yosoku  no yes
##         N 986 261
##         Y 161 392

この表を混同行列と呼びます。

ロジスティック回帰分析に限らず識別分析の各種アルゴリズムが有する予測能力を評価するための指標の多くは混同行列に基づいて算出されます。評価指標は多数ありますが、広く利用されているものを以下に示しておきます。

(tbl[1,1]+tbl[2,2])/(sum(tbl)) # 全体として何パーセントを正しく予測できたか ➡ この指標を「精度」といいます
## [1] 0.7655556
tbl[2,2]/sum(tbl[2,]) # 「反応するだろう」と予測した人の何パーセントが実際に反応したか ➡ この指標を「適合率」といいます
## [1] 0.7088608
tbl[2,2]/sum(tbl[,2]) # 実際に反応した人の何パーセントが事前に予測できていたか ➡ この指標を「再現率」といいます
## [1] 0.6003063

予測モデルの予測能力はテストデータに適用してみることによって評価できます。次に、テストデータについて同じ計算をします。

pred <- predict(model2, newdata=test, type="response") # テストデータについて反応確率を求める
yn.yosoku <- ifelse(pred > 0.5, "Y", "N") # 確率が0.5を超える人は"Y"、0.5未満の人は"N"とする
yn.yosoku <- as.factor(yn.yosoku) # "Y", "N"の文字を分類のための因子(ファクター)にしておく
tbl <- table(yn.yosoku, test$DM) # テストデータに含まれる200人の実際の行動を説明変数R,F,Mから正しく予測できたかを表にする
tbl
##          
## yn.yosoku  no yes
##         N 116  32
##         Y  16  36

トレーニングデータに対して求めた指標をテストデータについても求めましょう。

(tbl[1,1]+tbl[2,2])/(sum(tbl)) # 全体として何パーセントを正しく予測できたか ➡ この指標を「精度」といいます
## [1] 0.76
tbl[2,2]/sum(tbl[2,]) # 「反応するだろう」と予測した人の何パーセントが実際に反応したか ➡ この指標を「適合率」といいます
## [1] 0.6923077
tbl[2,2]/sum(tbl[,2]) # 実際に反応した人の何パーセントが事前に予測できていたか ➡ この指標を「再現率」といいます
## [1] 0.5294118

Rコマンダーでは常にた一つのデータセット(データフレーム)が計算対象になっています。そのため、アクティブ・データセットを用いて推定した予測モデルを他のデータセットに対して適用するという発想がないのだと思われます。というより、西山が経済分析を続けてきた長い間、トレーニングデータとテストデータを分けて予測能力を評価するという方法論はほぼ無かったと言えます。手元のデータは全て使用することが、特にデータ数が限られた状態においては、より正確な結果を得る、つまり推定誤差をより小さくするための王道でした。この辺にデータ・サイエンス時代の新しい発想が見られるように感じています。

実際の分析現場では、データを精細にフォローしようと過剰にモデルを複雑にする結果、新しく追加されたデータの予測では失敗するというケースがままあります。これをオーバーフィッテイングと呼んでいます。このオーバーフィッテイングという用語も比較的最近になってクローズアップされてきたものです(悪い意味でのデータマイニングという表現はありましたが)。上の例では、トレーニングデータとテストデータで予測精度にそれほど大きな違いがなくオーバーフィッテイングは生じていないことが分かります。

注: 全データを用いた時の結果“model1”の精度についてはホームワークにしておきましょう。授業を履修した方はパワーポイントに記載しています。