以下はWindows10、R version 4.2.1で実行しています。

データを読み込むにあたって、作業場所の指定とそこにデータが置いてあることが前提になります。 R本体を操作している場合は、「ファイル」→「ディレクトリの変更」でデータの置いてある場所を指定するのが簡単です。 RStudioを操作している場合は、例えばデスクトップの「R」という名前のフォルダにデータがあるとすると

setwd("C:/Users/ユーザー名/Desktop/R")

を最初に実行するのがよいでしょう。ユーザー名は各自異なるので注意です。

使用するデータを読み込み、表示します。なお、R version 4.1以前で読み込む際には

data1 <- read.csv("ファイル名.csv", fileEncoding = "UTF-8-BOM")

のように、エンコードのオプションを指定する必要があります。version 4.2以降では必要ありませんので、以下ではオプションを指定していません。

data1 <- read.csv("ch10-12ex.csv")

使用するパッケージを読み込みますが、パッケージはインストールしておく必要があります。 以下のようにコマンドでインストールするか、RやRStudioからクリックでインストールすることもできます。

install.packages(“stargazer”, dependencies = TRUE)

パッケージの機能が使えるように読み込みます。

library(dplyr)
## 
##  次のパッケージを付け加えます: 'dplyr'
##  以下のオブジェクトは 'package:stats' からマスクされています:
## 
##     filter, lag
##  以下のオブジェクトは 'package:base' からマスクされています:
## 
##     intersect, setdiff, setequal, union
library(car)
##  要求されたパッケージ carData をロード中です
## 
##  次のパッケージを付け加えます: 'car'
##  以下のオブジェクトは 'package:dplyr' からマスクされています:
## 
##     recode
library(stargazer)
## 
## Please cite as:
##  Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
##  R package version 5.2.3. https://CRAN.R-project.org/package=stargazer
library(mfx)
##  要求されたパッケージ sandwich をロード中です
##  要求されたパッケージ lmtest をロード中です
##  要求されたパッケージ zoo をロード中です
## 
##  次のパッケージを付け加えます: 'zoo'
##  以下のオブジェクトは 'package:base' からマスクされています:
## 
##     as.Date, as.Date.numeric
##  要求されたパッケージ MASS をロード中です
## 
##  次のパッケージを付け加えます: 'MASS'
##  以下のオブジェクトは 'package:dplyr' からマスクされています:
## 
##     select
##  要求されたパッケージ betareg をロード中です
library(erer)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(MASS)

12-1

使用する変数の準備をします。

data1 <- data1 %>% mutate(
  age=q10_5,
  agecl=as.factor(recode(age,'20:29=1;30:39=2;40:49=3;50:59=4;60:69=5')),
  fem=recode(gender,'2=1; 1=0'),
  mar=recode(q10_7,'1=0; 2=1; 3:9=NA'),
  edu=as.factor(recode(q10_12,'1:2=1; 3:4=2; 5:6=3; 7:9=NA')),
  wrk=as.factor(recode(q10_11,'1:3=1; 4:7=2; 9:10=3; 8=NA; 11:99=NA')),
  smk=recode(q10_1,'1=1; 2:3=0; 9=NA'),
  hap=as.factor(recode(q04_1,'1=5;2=4;3=3;4=2;5=1;9=NA')))

リコードの確認をします。

table(data1$gender, data1$fem, useNA = "ifany")
##    
##        0    1
##   1 1556    0
##   2    0 1191
table(data1$q10_7, data1$mar, useNA = "ifany")
##    
##        0    1 <NA>
##   1  892    0    0
##   2    0 1734    0
##   3    0    0   93
##   9    0    0   28
table(data1$q10_12, data1$edu, useNA = "ifany")
##    
##        1    2    3 <NA>
##   1   25    0    0    0
##   2  597    0    0    0
##   3    0  177    0    0
##   4    0  327    0    0
##   5    0    0 1391    0
##   6    0    0  184    0
##   7    0    0    0   12
##   9    0    0    0   34
table(data1$q10_11, data1$wrk, useNA = "ifany")
##     
##        1   2   3 <NA>
##   1   77   0   0    0
##   2  329   0   0    0
##   3  773   0   0    0
##   4    0 303   0    0
##   5    0  65   0    0
##   6    0 207   0    0
##   7    0  20   0    0
##   8    0   0   0  113
##   9    0   0 435    0
##   10   0   0 335    0
##   11   0   0   0   49
##   99   0   0   0   41
table(data1$age, data1$agecl)
##     
##       1  2  3  4  5
##   20 20  0  0  0  0
##   21 24  0  0  0  0
##   22 35  0  0  0  0
##   23 33  0  0  0  0
##   24 35  0  0  0  0
##   25 48  0  0  0  0
##   26 61  0  0  0  0
##   27 62  0  0  0  0
##   28 69  0  0  0  0
##   29 69  0  0  0  0
##   30  0 42  0  0  0
##   31  0 42  0  0  0
##   32  0 48  0  0  0
##   33  0 53  0  0  0
##   34  0 40  0  0  0
##   35  0 56  0  0  0
##   36  0 60  0  0  0
##   37  0 90  0  0  0
##   38  0 66  0  0  0
##   39  0 88  0  0  0
##   40  0  0 55  0  0
##   41  0  0 48  0  0
##   42  0  0 46  0  0
##   43  0  0 44  0  0
##   44  0  0 41  0  0
##   45  0  0 40  0  0
##   46  0  0 52  0  0
##   47  0  0 46  0  0
##   48  0  0 47  0  0
##   49  0  0 38  0  0
##   50  0  0  0 55  0
##   51  0  0  0 68  0
##   52  0  0  0 67  0
##   53  0  0  0 52  0
##   54  0  0  0 58  0
##   55  0  0  0 49  0
##   56  0  0  0 46  0
##   57  0  0  0 38  0
##   58  0  0  0 54  0
##   59  0  0  0 36  0
##   60  0  0  0  0 83
##   61  0  0  0  0 88
##   62  0  0  0  0 80
##   63  0  0  0  0 78
##   64  0  0  0  0 94
##   65  0  0  0  0 85
##   66  0  0  0  0 79
##   67  0  0  0  0 62
##   68  0  0  0  0 49
##   69  0  0  0  0 28
table(data1$q10_1, data1$smk, useNA = "ifany")
##    
##        0    1 <NA>
##   1    0  419    0
##   2  721    0    0
##   3 1581    0    0
##   9    0    0   26
table(data1$q04_1, data1$hap, useNA = "ifany")
##    
##        1    2    3    4    5 <NA>
##   1    0    0    0    0  310    0
##   2    0    0    0 1289    0    0
##   3    0    0  577    0    0    0
##   4    0  352    0    0    0    0
##   5  187    0    0    0    0    0
##   9    0    0    0    0    0   32

12-2

ロジット・モデルを推定します。

logit <- glm(smk~agecl+fem+mar+edu+wrk, family=binomial(link=logit), data=data1)
stargazer(logit, type="text",star.cutoffs=c(0.1,0.05,0.01),keep.stat = c("n","ll","rsq"))
## 
## ==========================================
##                    Dependent variable:    
##                ---------------------------
##                            smk            
## ------------------------------------------
## agecl2                    0.124           
##                          (0.227)          
##                                           
## agecl3                   0.454*           
##                          (0.233)          
##                                           
## agecl4                   0.409*           
##                          (0.235)          
##                                           
## agecl5                    0.081           
##                          (0.249)          
##                                           
## fem                     -1.087***         
##                          (0.148)          
##                                           
## mar                       0.166           
##                          (0.143)          
##                                           
## edu2                     -0.052           
##                          (0.177)          
##                                           
## edu3                    -0.593***         
##                          (0.140)          
##                                           
## wrk2                     -0.129           
##                          (0.152)          
##                                           
## wrk3                    -0.490***         
##                          (0.173)          
##                                           
## Constant                -1.156***         
##                          (0.223)          
##                                           
## ------------------------------------------
## Observations              2,416           
## Log Likelihood          -986.252          
## ==========================================
## Note:          *p<0.1; **p<0.05; ***p<0.01

20代に比べて40代、50代でいずれも10%水準で有意に喫煙確率が高いことがわかります。

また、女性、大学・大学院、無職の場合、いずれもベースカテゴリーに比べて1%水準で有意に喫煙確率が低いことがわかります。

既婚であることは有意ではなく、影響があるかどうかわからないという結果となっています。

マクファデンの疑似決定係数を計算します。

1-(logit$deviance/logit$null.deviance)
## [1] 0.05886078

平均的な限界効果を計算します。

logitmfx(smk~agecl+fem+mar+edu+wrk, data=data1, atmean=FALSE) 
## Call:
## logitmfx(formula = smk ~ agecl + fem + mar + edu + wrk, data = data1, 
##     atmean = FALSE)
## 
## Marginal Effects:
##             dF/dx  Std. Err.       z     P>|z|    
## agecl2  0.0159058  0.0296909  0.5357  0.592158    
## agecl3  0.0621881  0.0346040  1.7971  0.072314 .  
## agecl4  0.0550559  0.0339508  1.6216  0.104881    
## agecl5  0.0102393  0.0319074  0.3209  0.748282    
## fem    -0.1263771  0.0158269 -7.9849 1.406e-15 ***
## mar     0.0203696  0.0172088  1.1837  0.236541    
## edu2   -0.0064067  0.0217286 -0.2948  0.768109    
## edu3   -0.0769470  0.0186583 -4.1240 3.723e-05 ***
## wrk2   -0.0158316  0.0181964 -0.8700  0.384277    
## wrk3   -0.0573417  0.0187257 -3.0622  0.002197 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## dF/dx is for discrete change for the following variables:
## 
##  [1] "agecl2" "agecl3" "agecl4" "agecl5" "fem"    "mar"    "edu2"   "edu3"  
##  [9] "wrk2"   "wrk3"

平均的な限界効果で見ると、女性は男性に比べて12.6%ポイント喫煙確率が低いことがわかります。また、大学・大学院卒は高校以下卒に比べて7.7%ポイント喫煙確率が低くなっています。無職の場合は、正規職と比べて5.7%ポイント確率が低くなります。

平均での限界効果を計算します。

logitmfx(smk~agecl+fem+mar+edu+wrk, data=data1, atmean=TRUE) 
## Call:
## logitmfx(formula = smk ~ agecl + fem + mar + edu + wrk, data = data1, 
##     atmean = TRUE)
## 
## Marginal Effects:
##             dF/dx  Std. Err.       z     P>|z|    
## agecl2  0.0151617  0.0283837  0.5342  0.593224    
## agecl3  0.0601689  0.0340133  1.7690  0.076897 .  
## agecl4  0.0531418  0.0332130  1.6000  0.109591    
## agecl5  0.0097479  0.0304242  0.3204  0.748664    
## fem    -0.1241191  0.0156490 -7.9314 2.166e-15 ***
## mar     0.0192825  0.0162425  1.1872  0.235165    
## edu2   -0.0060777  0.0205860 -0.2952  0.767815    
## edu3   -0.0733143  0.0178385 -4.1099 3.958e-05 ***
## wrk2   -0.0149767  0.0171492 -0.8733  0.382488    
## wrk3   -0.0546154  0.0178874 -3.0533  0.002264 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## dF/dx is for discrete change for the following variables:
## 
##  [1] "agecl2" "agecl3" "agecl4" "agecl5" "fem"    "mar"    "edu2"   "edu3"  
##  [9] "wrk2"   "wrk3"

平均での限界効果もほぼ同じ結果となっています。

オッズ比を計算します。

logitor(smk~agecl+fem+mar+edu+wrk, data=data1) 
## Call:
## logitor(formula = smk ~ agecl + fem + mar + edu + wrk, data = data1)
## 
## Odds Ratio:
##        OddsRatio Std. Err.       z     P>|z|    
## agecl2  1.132344  0.257227  0.5471  0.584283    
## agecl3  1.574769  0.366790  1.9497  0.051216 .  
## agecl4  1.504734  0.354294  1.7354  0.082662 .  
## agecl5  1.084191  0.270044  0.3245  0.745530    
## fem     0.337309  0.050016 -7.3291 2.318e-13 ***
## mar     1.180416  0.168837  1.1596  0.246192    
## edu2    0.949642  0.168130 -0.2918  0.770403    
## edu3    0.552493  0.077344 -4.2382 2.253e-05 ***
## wrk2    0.878884  0.133290 -0.8513  0.394620    
## wrk3    0.612367  0.105668 -2.8421  0.004482 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

オッズ比も推定された係数の正負に従って、1より大きくなったり小さくなったりしていることがわかります。

具体的には、女性は男性に比べてオッズが0.34倍、大学・大学院卒は高校以下卒に比べてオッズが0.55倍、無職の場合は、正規職と比べてオッズが0.61倍となっていることがわかります。

12-3

順序ロジット・モデルを推定します。

ologit <- polr(hap~agecl+fem+mar+edu+wrk, data=data1, method = "logistic")
summary(ologit)
## 
## Re-fitting to get Hessian
## Call:
## polr(formula = hap ~ agecl + fem + mar + edu + wrk, data = data1, 
##     method = "logistic")
## 
## Coefficients:
##            Value Std. Error  t value
## agecl2 -0.231305    0.13514 -1.71160
## agecl3 -0.244836    0.14532 -1.68480
## agecl4 -0.544231    0.14589 -3.73046
## agecl5 -0.005085    0.14991 -0.03392
## fem     0.696633    0.08917  7.81199
## mar     1.419292    0.09717 14.60633
## edu2    0.348271    0.12129  2.87150
## edu3    0.388102    0.09692  4.00455
## wrk2   -0.222659    0.10290 -2.16393
## wrk3   -0.386496    0.10716 -3.60688
## 
## Intercepts:
##     Value    Std. Error t value 
## 1|2  -1.6598   0.1535   -10.8146
## 2|3  -0.3817   0.1419    -2.6903
## 3|4   0.7898   0.1425     5.5412
## 4|5   3.3983   0.1585    21.4392
## 
## Residual Deviance: 6262.628 
## AIC: 6290.628 
## ( 344 個の観測値が欠損のため削除されました )

疑似決定係数の計算で使用するために、推定に使用された対象をマークします。

data1$used <- TRUE;
data1$used[na.action(ologit)] <- FALSE;
table(data1$used)
## 
## FALSE  TRUE 
##   344  2403

独立変数のないモデルを推定します。

ologitn <- polr(hap~1, data=data1, subset=used==1, method = "logistic")
summary(ologitn)
## 
## Re-fitting to get Hessian
## Call:
## polr(formula = hap ~ 1, data = data1, subset = used == 1, method = "logistic")
## 
## No coefficients
## 
## Intercepts:
##     Value    Std. Error t value 
## 1|2  -2.6205   0.0811   -32.3015
## 2|3  -1.4274   0.0516   -27.6417
## 3|4  -0.3885   0.0416    -9.3454
## 4|5   2.0018   0.0630    31.7745
## 
## Residual Deviance: 6621.112 
## AIC: 6629.112

マクファデンの疑似決定係数を計算します。

1-(logLik(ologit)/logLik(ologitn))
## 'log Lik.' 0.05414252 (df=14)
stargazer(ologit, type="text",star.cutoffs=c(0.1,0.05,0.01),keep.stat = c("n","ll","rsq"))
## 
## ========================================
##                  Dependent variable:    
##              ---------------------------
##                          hap            
## ----------------------------------------
## agecl2                 -0.231*          
##                        (0.135)          
##                                         
## agecl3                 -0.245*          
##                        (0.145)          
##                                         
## agecl4                -0.544***         
##                        (0.146)          
##                                         
## agecl5                 -0.005           
##                        (0.150)          
##                                         
## fem                   0.697***          
##                        (0.089)          
##                                         
## mar                   1.419***          
##                        (0.097)          
##                                         
## edu2                  0.348***          
##                        (0.121)          
##                                         
## edu3                  0.388***          
##                        (0.097)          
##                                         
## wrk2                  -0.223**          
##                        (0.103)          
##                                         
## wrk3                  -0.386***         
##                        (0.107)          
##                                         
## ----------------------------------------
## Observations            2,403           
## ========================================
## Note:        *p<0.1; **p<0.05; ***p<0.01

20代に比べて30代、40代は10%水準で有意に幸福度が低く、50代は1%水準で有意に幸福度が低くなっていることがわかります。 また、女性、既婚者、高学歴の人はいずれもベースカテゴリーに比べて1%水準で有意に幸福度が高く、正規以外の職や無職の人は、正規の人に比べてそれぞれ5%水準、1%水準で有意に幸福度が低くなっていることもわかります。

念のため、閾値の有意性の確認です。

ctable <- coef(summary(ologit))
## 
## Re-fitting to get Hessian
p <- pnorm(abs(ctable[, "t value"]), lower.tail=FALSE)*2
(ctable <- cbind(ctable, "p value"=p))
##               Value Std. Error      t value       p value
## agecl2 -0.231305362 0.13514011  -1.71159672  8.697101e-02
## agecl3 -0.244836175 0.14532082  -1.68479770  9.202761e-02
## agecl4 -0.544231084 0.14588836  -3.73046269  1.911284e-04
## agecl5 -0.005084938 0.14991363  -0.03391911  9.729417e-01
## fem     0.696632790 0.08917485   7.81198735  5.629321e-15
## mar     1.419291939 0.09716964  14.60633062  2.559360e-48
## edu2    0.348270898 0.12128530   2.87150142  4.085269e-03
## edu3    0.388102368 0.09691525   4.00455402  6.213459e-05
## wrk2   -0.222658980 0.10289572  -2.16392851  3.046984e-02
## wrk3   -0.386495793 0.10715528  -3.60687570  3.099060e-04
## 1|2    -1.659773268 0.15347475 -10.81463427  2.934608e-27
## 2|3    -0.381736606 0.14189456  -2.69028355  7.139133e-03
## 3|4     0.789814558 0.14253417   5.54122967  3.003550e-08
## 4|5     3.398273374 0.15850729  21.43922508 5.756422e-102

オッズ比

係数の推定値が正の場合、オッズ比は1より大きく、負の場合は1より小さくなっています。 女性は、男性に比べてより高い幸福度を選ぶオッズが2.01倍となっていることがわかります。 また、既婚の人は未婚の人に比べてより高い幸福度を選ぶオッズが4.13倍となっています。

exp(coef(ologit))
##    agecl2    agecl3    agecl4    agecl5       fem       mar      edu2      edu3 
## 0.7934971 0.7828328 0.5802878 0.9949280 2.0069834 4.1341921 1.4166160 1.4741807 
##      wrk2      wrk3 
## 0.8003878 0.6794336

限界効果

ここでは平均での限界効果が示されています。 女性は、最も低い幸福度(1)を選ぶ確率が男性に比べて3.4%ポイント低く、最も高い幸福度(5)を選ぶ確率が6.6%ポイント高くなっていることがわかります。 また、既婚の人は、最も低い幸福度(1)を選ぶ確率が未婚の人に比べて9.7%ポイント低く、最も高い幸福度(5)を選ぶ確率が10.7%ポイント高くなっていることがわかります。

me_ol <- ocME(w = ologit, digits=4)
## 
## Re-fitting to get Hessian
me_ol
##        effect.1 effect.2 effect.3 effect.4 effect.5
## agecl2   0.0124   0.0214   0.0221  -0.0360  -0.0200
## agecl3   0.0134   0.0229   0.0232  -0.0385  -0.0208
## agecl4   0.0322   0.0527   0.0481  -0.0895  -0.0435
## agecl5   0.0003   0.0005   0.0005  -0.0008  -0.0005
## fem     -0.0343  -0.0607  -0.0685   0.0973   0.0662
## mar     -0.0969  -0.1402  -0.1021   0.2324   0.1068
## edu2    -0.0161  -0.0294  -0.0356   0.0466   0.0345
## edu3    -0.0203  -0.0353  -0.0375   0.0587   0.0345
## wrk2     0.0119   0.0206   0.0213  -0.0346  -0.0193
## wrk3     0.0210   0.0360   0.0365  -0.0604  -0.0331