MENU

R でロジスティック回帰を行う方法

タイタニック号は、1912年4月14日の夜、氷山に激突し、北大西洋の底に1,500名以上の命と一緒に沈んだ。

乗客乗員の生存・死亡のデータを用いて、ロジスティック回帰分析を実行してみる。

>>もう統計で悩むのは終わりにしませんか? 

↑期間・数量限定で無料プレゼント中!

目次

タイタニック号の生存・死亡データはどこにあるのか?

R はインストールするとデフォルトで使用可能な状態になっている。

datasets パッケージの文字通り Titanic という名前のデータだ。

Titanic の内容を確認する

str()で内容を確認してみる。

str(Titanic)

通常のdata frameとは異なる構造になっている。

> str(Titanic)
'table' num [1:4, 1:2, 1:2, 1:2] 0 0 35 0 0 0 17 0 118 154 ...
- attr(*, "dimnames")=List of 4
..$ Class   : chr [1:4] "1st" "2nd" "3rd" "Crew"
..$ Sex     : chr [1:2] "Male" "Female"
..$ Age     : chr [1:2] "Child" "Adult"
..$ Survived: chr [1:2] "No" "Yes"

データ自体を表示させてみる。

Titanic

Child, AdultとSurvived Yes, Noの4つに分かれたClassとSexの分割表が表示された。

このような形式で格納されている。

> Titanic
, , Age = Child, Survived = No
Sex
Class  Male Female
1st     0      0
2nd     0      0
3rd    35     17
Crew    0      0
, , Age = Adult, Survived = No
Sex
Class  Male Female
1st   118      4
2nd   154     13
3rd   387     89
Crew  670      3
, , Age = Child, Survived = Yes
Sex
Class  Male Female
1st     5      1
2nd    11     13
3rd    13     14
Crew    0      0
, , Age = Adult, Survived = Yes
Sex
Class  Male Female
1st    57    140
2nd    14     80
3rd    75     76
Crew  192     20

通常のデータフレーム状にするには、as.data.frame()を使う。

as.data.frame(Titanic)

4つの変数の組み合わせごとの人数というデータの形に変形された。

> as.data.frame(Titanic)
Class    Sex   Age Survived Freq
1    1st   Male Child       No    0
2    2nd   Male Child       No    0
3    3rd   Male Child       No   35
4   Crew   Male Child       No    0
5    1st Female Child       No    0
6    2nd Female Child       No    0
7    3rd Female Child       No   17
8   Crew Female Child       No    0
9    1st   Male Adult       No  118
10   2nd   Male Adult       No  154
11   3rd   Male Adult       No  387
12  Crew   Male Adult       No  670
13   1st Female Adult       No    4
14   2nd Female Adult       No   13
15   3rd Female Adult       No   89
16  Crew Female Adult       No    3
17   1st   Male Child      Yes    5
18   2nd   Male Child      Yes   11
19   3rd   Male Child      Yes   13
20  Crew   Male Child      Yes    0
21   1st Female Child      Yes    1
22   2nd Female Child      Yes   13
23   3rd Female Child      Yes   14
24  Crew Female Child      Yes    0
25   1st   Male Adult      Yes   57
26   2nd   Male Adult      Yes   14
27   3rd   Male Adult      Yes   75
28  Crew   Male Adult      Yes  192
29   1st Female Adult      Yes  140
30   2nd Female Adult      Yes   80
31   3rd Female Adult      Yes   76
32  Crew Female Adult      Yes   20

データフレームに転換したdatで計算していく。

dat <- as.data.frame(Titanic)

性別の相対生存オッズ比をロジスティック回帰モデルで計算する

単変量のロジスティック回帰

性別と生存・死亡を掛け合わせただけのシンプルなオッズ比をロジスティック回帰で計算してみる。

glm()を使い、family=binomialとする。「~」の左に生存・死亡のデータ Survived 、右に性別データ Sexを配置する。

今回のデータは人数の集計データなので、weights=Freqを付け加える。

生データでないときにはこれが必要だ。

logi1 <- glm(Survived~Sex,weights=Freq,data=dat,family=binomial)
summary(logi1)

結果は、logオッズは、男性を0とすると、女性は2.3172と計算された。

統計学的に有意である。

> logi1 <- glm(Survived~Sex,weights=Freq,data=dat,family=binomial)
> summary(logi1)
Call:
glm(formula = Survived ~ Sex, family = binomial, data = dat,
weights = Freq)
Deviance Residuals:
Min       1Q   Median       3Q      Max
-17.869   -3.455    0.000    5.969   24.405
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept)  -1.3128     0.0588  -22.32   <2e-16 ***
SexFemale     2.3172     0.1196   19.38   <2e-16 ***
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2769.5  on 23  degrees of freedom
Residual deviance: 2335.0  on 22  degrees of freedom
AIC: 2339
Number of Fisher Scoring iterations: 5

対数を真数に変換したほうがわかりやすい。

自前の関数 rr.95ci() を使う。

rr.95ci <- function(x){
res <- exp(cbind(coef(x),confint(x)))
colnames(res) <- c("RR","LL(2.5%)","UL(97.5%)")
round(res,2)
}

rr.95ci は Relative Risk and 95% Confidence Intervalの略だ。

rr.95ci(logi1)

女性のオッズ比は、男性を1とすると、10.15と計算された。

それだけ優先されて助けられたという結果だ。

> rr.95ci(logi1)
Waiting for profiling to be done...
RR LL(2.5%) UL(97.5%)
(Intercept)  0.27     0.24      0.30
SexFemale   10.15     8.05     12.86

Fisher Exact Test で確認してみる

2×2の分割表のデータに対して、Fisher Exact Test を実施してみる。

ロジスティック回帰と同様の結果になるか確認してみた。

apply()で、性別と生存・死亡のデータの分割表を、他の要因は合計するという処置をする。

そのテーブルを行列としてFisher Exact Testを実施する。

apply(Titanic,c(2,4),sum)
fisher.test(apply(Titanic,c(2,4),sum))

テーブルの数値を見れば、一目瞭然で、男性に比べ女性のほうが生き残っている。

Fisher Exact Testの結果、性別と生存・死亡は、統計学的有意に独立で、オッズ比は10.13であった。

これは先ほどのロジスティック回帰の結果と同様だ。

> apply(Titanic,c(2,4),sum)
Survived
Sex        No Yes
Male   1364 367
Female  126 344
> fisher.test(apply(Titanic,c(2,4),sum))
Fisher's Exact Test for Count Data
data:  apply(Titanic, c(2, 4), sum)
p-value < 2.2e-16
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
  7.97665 12.92916
sample estimates:
odds ratio 
   10.1319 

>>もう統計で悩むのは終わりにしませんか? 

↑1万人以上の医療従事者が購読中

客室・性別・年齢を加味した多重ロジスティック回帰モデルで分析する

客室 Class、性別 Sex、年齢 Ageを同時に投入した多変量モデルで分析してみる。

glm()に、family=binomialを加えるのは同様。「~」の左は同様にSurvived、右はClass, Sex, Ageを「+」でつないで投入。

logi2 <- glm(Survived ~ Class+Sex+Age, weights=Freq, family=binomial, data=dat)
summary(logi2)
rr.95ci(logi2)

結果として全部の説明変数が統計学的有意であった。

一等客室の乗客に比べ、二等、三等、乗務員は誰もが生き残れなかった。

女性のほうが生き残ったのは単変量の結果と同じ。

子供に比べ大人のほうが生き残れなかった。

子供を優先したということだろう。

> summary(logi2)
Call:
glm(formula = Survived ~ Class + Sex + Age, family = binomial,
data = dat, weights = Freq)
Deviance Residuals:
Min       1Q   Median       3Q      Max
-18.505   -4.247    0.000    4.747   23.915
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept)   0.6853     0.2730   2.510   0.0121 *
Class2nd     -1.0181     0.1960  -5.194 2.05e-07 ***
Class3rd     -1.7778     0.1716 -10.362  < 2e-16 ***
ClassCrew    -0.8577     0.1573  -5.451 5.00e-08 ***
SexFemale     2.4201     0.1404  17.236  < 2e-16 ***
AgeAdult     -1.0615     0.2440  -4.350 1.36e-05 ***
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2769.5  on 23  degrees of freedom
Residual deviance: 2210.1  on 18  degrees of freedom
AIC: 2222.1
Number of Fisher Scoring iterations: 5
> rr.95ci(logi2)
Waiting for profiling to be done...
RR LL(2.5%) UL(97.5%)
(Intercept)  1.98     1.16      3.39
Class2nd     0.36     0.25      0.53
Class3rd     0.17     0.12      0.24
ClassCrew    0.42     0.31      0.58
SexFemale   11.25     8.57     14.87
AgeAdult     0.35     0.21      0.56

Fisher Exact Testで単変量解析もやってみる

大人・子供と生存・死亡の関係をFisher Exact Testでも実行してみる。

apply(Titanic,c(3,4),sum)
fisher.test(apply(Titanic,c(3,4),sum))

子供のほうが生存した割合が高そうだ。

> apply(Titanic,c(3,4),sum)
Survived
Age       No Yes
Child   52  57
Adult 1438 654

大人のほうが統計学的有意に生き残れなく、オッズ比は0.415であった。

> fisher.test(apply(Titanic,c(3,4),sum))
Fisher's Exact Test for Count Data
data:  apply(Titanic, c(3, 4), sum)
p-value = 1.234e-05
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.2760923 0.6228448
sample estimates:
odds ratio 
 0.4150843 

客室クラスと生存・死亡の単変量解析はどうやったいいか?

Class変数は、客室クラスと乗務員を合わせて、4つに分かれている。

apply(Titanic,c(1,4),sum)

4×2の分割表の時はどうしたらよいか?

> apply(Titanic,c(1,4),sum)
Survived
Class   No Yes
1st  122 203
2nd  167 118
3rd  528 178
Crew 673 212

epitools パッケージを使う。

Epidemiology (疫学) のツールが詰まったパッケージである。

最初に一回だけインストールする。

install.packages("epitools")

library()で呼び出す。

library(epitools)

oddsratio()を使うと、一行目をオッズ1として、二行目以降のオッズ比を計算してくれる。

oddsratio(apply(Titanic,c(1,4),sum))

$measureの項に結果があり、一等客室の乗客に比べ、二等は0.425、三等は0.203、乗務員は0.190と計算されている。

多変量モデル中の結果とおおむね一致する。

> oddsratio(apply(Titanic,c(1,4),sum))
$data
Survived
Class     No Yes Total
1st    122 203   325
2nd    167 118   285
3rd    528 178   706
Crew   673 212   885
Total 1490 711  2201
$measure
odds ratio with 95% C.I.
Class   estimate     lower     upper
1st  1.0000000        NA        NA
2nd  0.4254346 0.3064855 0.5884387
3rd  0.2030991 0.1528567 0.2686306
Crew 0.1897539 0.1441302 0.2487196
$p.value
two-sided
Class    midp.exact fisher.exact   chi.square
1st            NA           NA           NA
2nd  2.029144e-07 2.777190e-07 2.026267e-07
3rd  0.000000e+00 3.675395e-30 1.141202e-30
Crew 0.000000e+00 1.811851e-34 6.880615e-36
$correction
[1] FALSE
attr(,"method")
[1] "median-unbiased estimate & mid-p exact CI"

まとめ

悲劇の大事故を起こしたタイタニック号の生存・死亡データを、ロジスティック回帰モデルで分析してみた。

多変量の結果だけでなく、単変量の結果とも突き合わせながら、実施した。

ロジスティック回帰モデルの分析方法は、glm()を使い、family=binomialを追加する。

今回のように集計値のデータセットの場合、as.data.frame()でデータフレームに変換し、weights=Freq(Freqは頻度変数の名前)を忘れないようにする。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

リサーチクエスチョン探し?データ分析?論文投稿?、、、で、もう悩まない!

第1章臨床研究ではなぜ統計が必要なのか?計画することの重要性
  • 推定ってどんなことをしているの?
  • 臨床研究を計画するってどういうこと?
  • どうにかして標本平均を母平均に近づけられないか?
第2章:研究目的をどれだけ明確にできるのかが重要
  • データさえあれば解析でどうにかなる、という考え方は間違い
  • 何を明らかにしたいのか? という研究目的が重要
  • 研究目的は4種類に分けられる
  • 統計専門家に相談する上でも研究目的とPICOを明確化しておく
第3章:p値で結果が左右される時代は終わりました
  • アメリカ統計協会(ASA)のp値に関する声明で指摘されていること
  • そうは言っても、本当に有意差がなくてもいいの…?
  • なぜ統計専門家はp値を重要視していないのか
  • 有意差がない時に「有意な傾向があった」といってもいい?
  • 統計を放置してしまうと非常にまずい
第4章:多くの人が統計を苦手にする理由
  • 残念ながら、セミナー受講だけで統計は使えません。
  • インプットだけで統計が使えない理由
  • どうやったら統計の判断力が鍛えられるか?
  • 統計は手段なので正解がないため、最適解を判断する力が必要
第5章:統計を使えるようになるために今日から何をすれば良いか?
  • 論文を読んで統計が使えるようになるための5ステップ
第6章:統計を学ぶために重要な環境
  • 統計の3つの力をバランスよく構築する環境

以下のボタンをクリックして、画面に出てくる指示に従って、必要事項を記入してください。

この記事を書いた人

統計 ER ブログ執筆者

元疫学研究者

統計解析が趣味

コメント

コメント一覧 (1件)

コメントする

目次