<- 45
mux <- 50
muy <- 55
muz <- 25
n <- 10
sd0 <- 2
multip
<- rnorm(n, mean = 0, sd = sd0)
uj <- uj - mean(uj)
uj
<- data.frame("group" = rep("x", n), "score" = mux + uj)
x <- data.frame("group" = rep("y", n), "score" = muy + uj)
y <- data.frame("group" = rep("z", n), "score" = muz + uj)
z
<- data.frame("group"=rep("x", n), "score" = mux + multip*uj)
x2 <- data.frame("group"=rep("y", n), "score" = muy + multip*uj)
y2 <- data.frame("group"=rep("z", n), "score" = muz + multip*uj)
z2
<- rbind(x, y, z) # ; str(d01)
d01 <- rbind(x2, y2, z2)
d02
<- min(d01$score, d02$score) - 5
min_y <- max(d01$score, d02$score) + 5
max_y
<- anova(aov(score ~ group, data = d01))
ano1 <- anova(aov(score ~ group, data = d02))
ano2
<- by(d01$score, d01$group, mean)
mean1 <- by(d02$score, d02$group, mean)
mean2
<- sprintf("mean(x, y, z)=(%.1f, %.1f, %.1f)", mean1[1], mean1[2], mean1[3])
g1.xlab <- sprintf("mean(x, y, z)=(%.1f, %.1f, %.1f)", mean2[1], mean2[2], mean2[3])
g2.xlab
<- ggplot(d01, aes(x = group, y = score)) +
g1 geom_boxplot(aes(color = group)) +
geom_jitter(alpha = .4, aes(color = group)) +
theme_classic() + ylim(min_y, max_y) +
theme(legend.position = "none") +
labs(title = sprintf("F(%d, %d)=%.3f, p-value=%.4f", ano1$Df[1], ano1$Df[2], ano1$"F value", ano1$"Pr(>F)"),
x = g1.xlab, y = "score")
<- ggplot(d02, aes(x = group, y = score)) +
g2 geom_boxplot(aes(color = group)) +
geom_jitter(alpha = .4, aes(color = group)) +
theme_classic() + ylim(min_y, max_y) +
theme(legend.position = "none") +
labs(title = sprintf("F(%d, %d)=%.3f, p-value=%.4f", ano2$Df[1], ano2$Df[2], ano2$"F value", ano2$"Pr(>F)"),
x=g2.xlab, y="")
『入門・社会統計学――2ステップで基礎から〔Rで〕学ぶ』
第7章 平均値の差の分散分析(ANOVA)
0 全体の章構成
1 1要因分散分析
グループ間の母平均の差を検定する分散分析,ANOVA(Analysis of Variance)の初歩について解説する。
分散分析は,級間変動と級内変動の比が核心。
級間変動は,級間分散,級間平方和で考えても同じ。群間,グループ間の(平均の)差を示す。何らかのグループ/カテゴリーに属する事で人々がどの程度違ってくるか,である。
級内変動は,級内分散,級内平方和で考えても同じ。同じグループ/カテゴリーに属する人達の間での個人差を示す。グループの効果を見る観点からすればこれは誤差の扱いになる。
実行するたびに結果が変わるので,例としては余り良くない場合もある。
(後から全く同じ結果を再現したい場合には,最初に set.seed( ) を使う。)
::grid.arrange(g1, g2, nrow = 1) gridExtra
<- ano1$Df[1]
df1 <- ano1$Df[2]
df2
<- .05; upr <- qf(.99, df1, df2)
p
curve(df(x, df1, df2),
xlim = c(0, upr),
bty = "n",
xlab = "",
ylab = "",
xaxt = "n",
col = "#339900",
main = paste("対応するF分布(df=", df1, ", ", df2, ")の確率",
round(p*100, 2), "%領域"))
abline(h = 0, col = "#33990080")
segments(x0 <- seq(qf(1-.05, df1, df2), upr, by = .01), 0,
df(x0, df1, df2),
x0, col = "#ff3333")
axis(side = 1,
at = seq(0, upr, by = 0.5),
col.axis = "#555555",
cex.axis = 0.8,
las = 1)
axis(side = 1,
at = c(round(qf(1-.05, df1, df2), 2)),
col.axis = "#ff0000",
cex.axis = 1,
las = 2)
1-1 偏差平方和(Sum of Squares)の分解
グループ j に属している個人 i の測定値を次のように変形して考えると,第二項の( )内が全体平均からのグループ j の平均の偏差,第三項の( )内がグループ j の平均からの個人 i の測定値の偏差となる。前者がグループ j に属することの効果を表し,後者は誤差として扱われる。
\[y_{ij}=\bar{y}+(\bar{y_j}-\bar{y})+(y_{ij}-\bar{y_j})\]
全体の偏差平方和は次のようになる。グループの数 m は慣習的に水準数と呼ぶ。
\[\sum_{j=1}^{m}\sum_{i=1}^{n_{j}}(y_{ij}-\bar{y})^2=\sum_{j=1}^{m}n_{j}(\bar{y_{j}}-\bar{y})^2+\sum_{j=1}^{m}\sum_{i=1}^{n_{j}}(y_{ij}-\bar{y_{j}})^2\] 左辺を総平方和\(SS_{T} (SS_{Total})\),右辺第一項を級間平方和(グループ間平方和)\(SS_{B} (SS_{Between})\),右辺第二項を級内平方和(グループ内平方和)\(SS_{W} (SS_{Within})\)と呼ぶ。そして級間平方和が関心の対象であるグループによる影響,級内平方和は誤差としての個人差となる。この平方和の分解が分散分析の根幹である。 \[SS_{Total}=SS_{Between}+SS_{Within}\]
1-2 ゼロ仮説(Null Hypothesis; H0)とF統計量
偏差平方和の分解の式
\[\sum_{j=1}^{m}\sum_{i=1}^{n_{j}}(y_{ij}-\bar{y})^2=\sum_{j=1}^{m}n_{j}(\bar{y_{j}}-\bar{y})^2+\sum_{j=1}^{m}\sum_{i=1}^{n_{j}}(y_{ij}-\bar{y_{j}})^2\] 測定値に等分散正規性\(y_{ij}\sim N(\mu,\sigma^2)\)が仮定できるとき,
ここで,「カイ二乗分布に従う統計量÷その自由度」という統計量が二つあったとき,その比が F 分布として定義されることを利用する。
\[F_{(df_{1},df_{2})}=\frac{\chi_{(df_{1})}^2/df_{1}}{\chi_{(df_{2})}^2/df_{2}}\] 平方和(Sum of Squares, SS)の分解の式の右辺の第一項と第二項をそれぞれの自由度で割った統計量を平均平方(Mean Square, MS)という。これは,自由度一つあたりの平方和という意味である。 \[MS_{Between}=\frac{SS_{Between}}{m-1}\] \[MS_{Within}=\frac{SS_{Within}}{n-m}\] そしてこの二つの平均平方の比は,自由度 m-1,n-m の F 分布に従うことが分かる。 \[\frac{MS_{Between}}{MS_{Within}}=\frac{SS_{Between}/(m-1)}{SS_{Within}/(n-m)}=\frac{(SS_{Between}/\sigma^2)/(m-1)}{(SS_{Within}/\sigma^2)/(n-m)}=F_{(m-1,n-m)}\] 母分散が分母と分子で約分されて消え去り,平均平方の比自体はデータから具体的に計算可能な値になっているので,平均平方の比である F 統計量によってゼロ仮説を検定することが可能になる。
グラフにいくつかオプションなどで装飾を施してみよう。
<- 5; n <- 50; p0 <- .05
m <- qf(p = p0, df1 = m-1, df2 = n-m, lower.tail = F)
F0 <- qf(min(p0/2, .01), df1 = m-1, df2 = n-m, lower.tail = F)
END
curve(df(x, df1 = m-1, df2 = n-m),
xlim = c(0, END), bty = "n",
xlab = "F統計量", ylab = "確率密度",
main = sprintf("自由度%d,%dのF分布の%.1f%%棄却域", m-1, n-m, p0 * 100))
axis(side = 1, at = F0, label = round(F0, 2),
col.axis = "red", las = 2)
segments(rej <- seq(F0, END, by = .02), 0,
df(rej, df1 = m-1, df2 = n-m), col = "red")
rej,
abline(h = 0, lty = 2, col = "grey")
1-3 4群の母平均差のF検定
いよいよ(一要因)分散分析を行う。aov( )
関数,lm( )
関数,oneway.test( )
関数のうち,まずは最初の二つを説明する。
次のスクリプトを実行すると,このF分布の5%棄却域(赤)とF値(紫)の関係をカラーで図示できる。関数ごとに分けて実行すると関数の意味が分かりやすい。
# F分布
<- (1950508/3)/(62254591/292) # F統計量
F0 <- 3; DF2 <- 292 # 自由度は関数のオプションの名称と区別する為敢えて大文字にした
DF1
curve(df(x, DF1, DF2), xlim = c(0, END <- 4), xaxp = c(0, END, 2),
bty = "n", family = "serif", xlab = "", ylab = "",
main = sprintf("自由度(%d, %d)のF分布の5%%棄却領域", DF1, DF2))
segments(x1 <- seq(x2 <- qf(.95, DF1, DF2), END, by = .02), 0,
df(x1, DF1, DF2), col = "red")
x1, axis(side = 1, at = round(x2, 3),
col = "red", col.axis = "red",
las = 2, family = "serif")
axis(side = 1, at = round(F0, 3),
col = "purple", col.axis = "purple",
las = 2, family = "serif")
なお,各種の分散説明率(R-squared, Eta-squared, partial Eta-squared)については,二元配置分散分析の2-1 平方和の分解の末尾に例示を付け加えておく。
1-4 多重比較(multiple comparison),事後検定(post-hoc test)
一つ一つの検定の有意水準をp1,そうした検定を3つ繰り返した場合の最終的な有意水準をp3とすると,p3 = p1 + p1 + p1 - 3*p1*p1 + p1*p1*p1 である。
p1を.05(5%)とすると,p3=.142625となる。そこでp1=.05/3とすると,p3は5%以内に収まる。
# 多重比較
<- .05
p1 <- p1*3 - 3*p1^2 + p1^3; p3 p3
[1] 0.142625
<- .05/3
p1 <- p1*3 - 3*p1^2 + p1^3; p3 p3
[1] 0.0491713
世帯年収fincomeと従業上の地位jobで実際にボンフェローニ法を実行してみよう。
共通の標準偏差を用いるか否かというオプションpool.sdによって結果が変わる。
本文ではデフォルトのpool.sd = Tの結果を述べたが,ここでは両方実行する。
(わざと,with( )を使った書き方と使わない書き方で示している。どう異なるか見比べて欲しい。)
# 共通の標準偏差を推定して検定(等分散性の仮定)
pairwise.t.test(data01$fincome, data01$job,
p.adjust.method = "bonferroni")
Pairwise comparisons using t tests with pooled SD
data: data01$fincome and data01$job
1 2 3
2 0.056 - -
3 0.414 1.000 -
4 0.482 1.000 1.000
P value adjustment method: bonferroni
# 等分散を仮定しないで検定
with(data01,
pairwise.t.test(fincome, job,
p.adjust.method = "bonferroni", pool.sd = F))
Pairwise comparisons using t tests with non-pooled SD
data: fincome and job
1 2 3
2 0.032 - -
3 0.524 1.000 -
4 0.728 1.000 1.000
P value adjustment method: bonferroni
デフォルトはプールした標準偏差を使う,つまり全ての群で等分散を仮定しているが,pool.sd = Fとすると各群での標準偏差を使用する(等分散を仮定しない)。
等分散を仮定しないt検定とはつまりWelchの検定であり,上の出力の後半は,各ペアでウェルチの検定を行って計算された有意確率に検定の回数(ここでは6回)をかけた結果が出力されている。
指定しうる多重比較の方法は,ボンフェローニ”bonferroni”,ホルム”holm”, ホッホベルク”hochberg”, ホンメル”hommel”, ベンジャミニとホッホベルク”BH”, ベンジャミニとイェクティエリ”BY”である。
bonferroni,holm,hochberg,hommelは”family-wise error rate(FWER)”を調整するものであるが,BHとBYは”false discovery rate(FDR)”を統制するものである。
以下のサイトの解説が分かり易い。
『大阪大学大学院医学系研究科 老年・腎臓内科学 腎臓内科』の多重比較解説(2019年9月3日閲覧)
hommel・等分散の例と,BH・不等分散の実行例を示しておく。
テューキー(Tukey)の多重比較
Tukey法は,例1の2行で実行し信頼区間を図示できるが,より見易くする為にオブジェクトの代入を活用し,グラフに少しオプションを指定したのが例2である。
1-5 等分散性の前提とウェルチ検定
2 2要因分散分析
2-1 平方和の分解
二要因分散分析でも,(偏差)平方和SSの分解が基本であることには変わらないが,各グループのサイズが異なる場合(非釣り合い型データ,アンバランスデータ,非直交なデータ)には分解の仕方が複数存在し,標準のaov( )
関数はその点で問題を生じる。
まずはデータの準備をする。分割表でも分かる様に,セルのサイズ(グループのサイズ)はまるでばらばらである。
また,投入する変数によって,有効ケース数が変化してしまう(後で対処する)。
## 二元配置の分散分析
$SEX <- factor(data01$sex, levels = 1:2,
data01labels = c("男性", "女性")) # 独立変数その1
with(data01, table("性別" = SEX, "従業上の地位" = JOB, useNA="ifany"))
従業上の地位
性別 正規 非正規 自営 無職 <NA>
男性 127 9 19 7 3
女性 55 83 19 61 1
次に,それぞれの一要因分散分析と,性別,従業上の地位の順に変数を並べた二要因分散分析の結果を表示する。一要因の場合とは,各独立変数(主効果)の平方和も有意確率も異なる。
anova(model30 <- aov(fincome ~ SEX, data01)) # 性別の一要因分散分析
anova(model31 <- aov(fincome ~ JOB, data01)) # 従業上の地位の一要因分散分析
anova(model32 <- aov(fincome ~ SEX + JOB, data01)) # 二要因分散分析,その1
ここで,独立変数の並べ順を変えてみよう。変数の並べ順を変えただけで,それぞれの独立変数の偏差平方和も有意確率もすっかり変わってしまった。
anova(model33 <- aov(fincome ~ JOB + SEX, data01)) # 二要因分散分析,その2
分散説明率(Proportion of variance explained)
ここで,効果サイズ(effect size)の指標である分散説明率について紹介しておこう。
分散分析では伝統的に\(\eta^2\)(イータの二乗)と云う単語・統計量が使用され,回帰分析では\(R^2\)(決定係数)が用いられてきた。
\(R^2\)は通常,モデル全体の説明率を示すのに用いられ,\(\eta^2\)は個々の要因の説明率を示すのに用いられる。
(重回帰分析では偏回帰係数のt検定は分散説明率の増加分についてのF検定と同値であるので,実際には回帰分析でも個々の要因の説明率を示すのにも使用可能である。)
世帯収入を,性別と従業上の地位で説明するモデルを,aov( )
とlm( )
で実行し,anova( )
やAnova( )
,heplotsパッケイジ中のetasq( )
関数に与えて出力結果を確認する。
2-2 交互作用項(interaction)
複数の要因(独立変数)が複合的に従属変数に影響を及ぼす事を,計量分析では「交互作用interaction」と呼ぶが,質的比較分析(QCA, Qualitative Comparative Analysis)でいう「結合因果conjunctural causation」と同種の考えであると言ってよいだろう。
以下,本文のスクリプトとその結果を,より装飾を施した形で紹介してゆく。
# 性別×従業上の地位によって8つの群に分けた時の世帯年収平均
# 本文では小数点以下が表示されているが,不要なので四捨五入する。
with(data01, round(tapply(fincome, list(SEX, JOB), mean, na.rm = T), 0))
正規 非正規 自営 無職
男性 749 388 723 105
女性 932 653 538 735
# 交互作用項を含むモデルの二つの書き方
aov(fincome ~ SEX + JOB + SEX:JOB, data01)
Call:
aov(formula = fincome ~ SEX + JOB + SEX:JOB, data = data01)
Terms:
SEX JOB SEX:JOB Residuals
Sum of Squares 84061 3428643 1885038 58807357
Deg. of Freedom 1 3 3 288
Residual standard error: 451.8763
Estimated effects may be unbalanced
88 observations deleted due to missingness
aov(fincome ~ SEX * JOB, data01)
Call:
aov(formula = fincome ~ SEX * JOB, data = data01)
Terms:
SEX JOB SEX:JOB Residuals
Sum of Squares 84061 3428643 1885038 58807357
Deg. of Freedom 1 3 3 288
Residual standard error: 451.8763
Estimated effects may be unbalanced
88 observations deleted due to missingness
# type I平方和による分散分析
anova(aov(fincome ~ SEX * JOB, data01))
anova(aov(fincome ~ JOB * SEX, data01))
# type II平方和による分散分析
Anova(aov(fincome ~ SEX * JOB, data01))
# type III平方和による分散分析
Anova(aov(fincome ~ SEX * JOB, data01), type=3)
平方和の分解方法によって結果が異なる事を確認しておこう。
平均は先に計算した通りだが,交互作用プロットの様なグラフではそれぞれのグループのケース数(グループサイズ)が全く分からないので,グループ毎の有効ケース数も計算しておくのが良い。
# 各グループ平均
with(data01, round(tapply(fincome, list(SEX, JOB), mean, na.rm=T), 0))
正規 非正規 自営 無職
男性 749 388 723 105
女性 932 653 538 735
# 各グループの有効ケース数
with(data01, tapply(fincome, list(SEX, JOB), function(x) sum(!is.na(x))))
正規 非正規 自営 無職
男性 101 6 14 5
女性 44 68 14 44
発展1 2群の母平均の差のt検定と1要因分散分析
性別による幸福度の平均の差の分析結果を再掲しておこう。
$happiness <- c(0:10)[data01$q1700 + 1]
data01
with(data01,
by(happiness, sex, mean, na.rm = T))
sex: 1
[1] 6.36646
------------------------------------------------------------
sex: 2
[1] 6.917051
with(data01,
by(happiness, sex, var, na.rm = T))
sex: 1
[1] 4.083618
------------------------------------------------------------
sex: 2
[1] 3.08568
with(data01,
by(happiness, sex, function(x) sum(!is.na(x))))
sex: 1
[1] 161
------------------------------------------------------------
sex: 2
[1] 217
var.test(happiness ~ sex, data01)
F test to compare two variances
data: happiness by sex
F = 1.3234, num df = 160, denom df = 216, p-value = 0.05555
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.9933775 1.7743088
sample estimates:
ratio of variances
1.323409
<- t.test(happiness ~ sex, var.equal = T, data01)
T01 T01
Two Sample t-test
data: happiness by sex
t = -2.8252, df = 376, p-value = 0.004977
alternative hypothesis: true difference in means between group 1 and group 2 is not equal to 0
95 percent confidence interval:
-0.9337912 -0.1673909
sample estimates:
mean in group 1 mean in group 2
6.366460 6.917051
これを,一要因分散分析で行ってみる。この例では等分散を仮定出来る為,関数は3種類あるので全て実行して見せよう。独立変数であるx(元はdata01$sex)はfactor型にすべきだが,二値変数の場合には結果に本質的な違いはない。
<- oneway.test(happiness ~ sex, var.equal = T, data01)
F02 <- anova(aov(happiness ~ sex, data01)) # anova(aov( )) と一致する
F01 <- anova(lm(happiness ~ sex, data01)) # anova(lm( ))と一致する
L01 F02
One-way analysis of means
data: happiness and sex
F = 7.9819, num df = 1, denom df = 376, p-value = 0.004977
F01
L01
t検定の結果とF検定の結果を並べて表示させよう。更に,オブジェクトにどんな情報が格納されているのかも一覧を確認しよう。
names(T01) T01;
Two Sample t-test
data: happiness by sex
t = -2.8252, df = 376, p-value = 0.004977
alternative hypothesis: true difference in means between group 1 and group 2 is not equal to 0
95 percent confidence interval:
-0.9337912 -0.1673909
sample estimates:
mean in group 1 mean in group 2
6.366460 6.917051
[1] "statistic" "parameter" "p.value" "conf.int" "estimate"
[6] "null.value" "stderr" "alternative" "method" "data.name"
names(F01) F01;
[1] "Df" "Sum Sq" "Mean Sq" "F value" "Pr(>F)"
names(F02) F02;
One-way analysis of means
data: happiness and sex
F = 7.9819, num df = 1, denom df = 376, p-value = 0.004977
[1] "statistic" "parameter" "p.value" "method" "data.name"
t分布の自由度とF分布の残差(級内)の自由度,有意確率同士が対応している事が分かる。
t統計量とF統計量の関係は,次の様に確認してみよう。
$statistic^2 T01
t
7.981851
$"F value" F01
[1] 7.981851 NA
$statistic F02
F
7.981851
t分布はマイナス領域とプラス領域がある。二乗すれば同じ値になる点が正負の二つある。F分布は全て非負である。どの様に対応しているだろうか。
下の様に確認すると,tが負の時と正の時の確率を合わせたものが,(tの二乗に等しい)Fの上側確率に等しい事が分かる。tの両側検定はFの上側検定に対応しているのである。
# t分布の下側確率と上側確率の和
pt( abs(T01$statistic), df = T01$parameter, lower.tail = F) + pt(-1*abs(T01$statistic), df = T01$parameter)
t
0.004976846
# F分布の上側確率
pf(F01$"F value"[1], df1 = F01$Df[1], df2 = F01$Df[2], lower.tail = F)
[1] 0.004976846
等分散を仮定出来ずにウェルチの検定を行った男女での世帯年収差はどうであろうか。
<- t.test(fincome ~ sex, data01)
T02 <- oneway.test(fincome ~ sex, data01)
F03 T02
Welch Two Sample t-test
data: fincome by sex
t = -0.756, df = 294.6, p-value = 0.4503
alternative hypothesis: true difference in means between group 1 and group 2 is not equal to 0
95 percent confidence interval:
-142.7534 63.5176
sample estimates:
mean in group 1 mean in group 2
697.4409 737.0588
F03
One-way analysis of means (not assuming equal variances)
data: fincome and sex
F = 0.57153, num df = 1.0, denom df = 294.6, p-value = 0.4503
$statistic^2 T02
t
0.5715288
$statistic F03
F
0.5715288
これもやはり,自由度,有意確率が一致し,t統計量の2乗とF統計量が一致している。anova(aov( ))
関数では等分散性が仮定出来ない分散分析を行う事は出来ない。
第7章の【練習問題】の解答
1) の答え
問題文で要求されていないコマンドも含んだスクリプトを掲載する。
<- factor(data01$edu2, levels=1:3, labels=c("高校", "短大", "四大"))
x <- data01$income
y
# まずは変数の分布を確認しておく
table(x, useNA="always")
x
高校 短大 四大 <NA>
128 123 125 8
table(y, useNA="always")
y
0 25 75 125 200 300 400 500 600 700 800 925 1125 1375 1750 2500
45 24 28 29 40 35 31 29 27 18 12 13 6 1 3 1
<NA>
42
# カテゴリー別の平均値,ケース数を求める
by(y, x, mean, na.rm=T)
x: 高校
[1] 283.6777
------------------------------------------------------------
x: 短大
[1] 236.4865
------------------------------------------------------------
x: 四大
[1] 536.7925
by(y, x, function(x) sum(!is.na(x)))
x: 高校
[1] 121
------------------------------------------------------------
x: 短大
[1] 111
------------------------------------------------------------
x: 四大
[1] 106
# 等分散性の検定
bartlett.test(y ~ x)
Bartlett test of homogeneity of variances
data: y by x
Bartlett's K-squared = 33.378, df = 2, p-value = 5.651e-08
# 等分散を仮定しない分散分析と,仮定する分散分析
oneway.test(y ~ x)
One-way analysis of means (not assuming equal variances)
data: y and x
F = 20.878, num df = 2.00, denom df = 210.05, p-value = 5.369e-09
anova(aov(y ~ x))
# 多重比較
TukeyHSD(aov(y ~ x))
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = y ~ x)
$x
diff lwr upr p adj
短大-高校 -47.1912 -144.5816 50.19921 0.4897002
四大-高校 253.1148 154.5337 351.69587 0.0000000
四大-短大 300.3060 199.6726 400.93929 0.0000000
2) の答え
まず,anova(aov( ))では独立変数の投入順が結果に影響する事を確認しておく(タイプⅠ平方和)。
“car”パッケイジのAnova( )関数(タイプⅡ平方和)ではそうした違いが生じない事を次に確認し,交互作用を含んだモデルも実行する。そして最後に交互作用プロットを描く。
<- factor(data01$sex, levels=1:2, labels=c("男性", "女性"))
x2
# anova(aov( ))では投入順で結果が変わる
anova(aov(y ~ x + x2))
anova(aov(y ~ x2 + x))
# install.packages("car", repos="https://cran.ism.ac.jp")
library("car")
Anova(aov(y ~ x + x2))
Anova(aov(y ~ x2 + x)) # "car"のAnova( )なら順番に左右されない
Anova(aov(y ~ x * x2)) # 交互作用項を含める
<- max(tapply(y, list(x, x2), mean, na.rm=T)) # y軸の最大値を自動で設定させる
MAX interaction.plot(x, x2, y, bty="l",
fun=function(x) mean(x, na.rm=T),
xlab="最終学歴", ylab="平均個人年収(万円)", family="serif",
main="交互作用プロット", ylim=c(0, MAX), col=c("blue", "red"))
3) の答え
交互作用を含むモデルを取り上げ,aov( ),anova( ),Anova( )の結果も比較してみる。
<- aov(y ~ x * x2)
model1 # aov( )のオブジェクトの主な内容 model1
Call:
aov(formula = y ~ x * x2)
Terms:
x x2 x:x2 Residuals
Sum of Squares 5658984 7807360 93424 25290094
Deg. of Freedom 2 1 2 332
Residual standard error: 275.9982
Estimated effects may be unbalanced
46 observations deleted due to missingness
names(model1)
[1] "coefficients" "residuals" "effects" "rank"
[5] "fitted.values" "assign" "qr" "df.residual"
[9] "na.action" "contrasts" "xlevels" "call"
[13] "terms" "model"
anova(model1) # anova( )の主な内容
names(anova(model1))
[1] "Df" "Sum Sq" "Mean Sq" "F value" "Pr(>F)"
Anova(model1) # Anova( )の主な内容
names(Anova(model1))
[1] "Sum Sq" "Df" "F value" "Pr(>F)"
model1の”coefficients”を表示させると以下の通りである。
$coefficients model1
(Intercept) x短大 x四大 x2女性 x短大:x2女性 x四大:x2女性
462.7551020 61.3189720 195.9750567 -300.9495465 -79.0769085 0.3589226
カテゴリごとの平均は以下の通りである。
tapply(y, list(x, x2), mean)
男性 女性
高校 NA 161.8056
短大 NA NA
四大 NA NA
これをよく見比べると,model1$coefficients
の(Intercept)は,高校―男性カテゴリの平均個人年収に一致している。また,「x2女性」の-300.9495465は,高校―男性と高校―女性の差にぴったり一致している。「x短大」の61.3189720は高校―男性と短大―男性の差にぴったり一致する。最終学歴においては「高校」が,性別においては「男性」が「基準カテゴリ」となっており,そこからの差が”coefficients”として計算されているのである。これは「ダミー変数を用いて,交互作用項も投入した重回帰分析」と同じである。
ちょっと難しいかも知れないが,この coefficients を次の様に合計すると,各カテゴリの平均が求められる。いずれも最後の列の Sum が,上で調べた各カテゴリの平均年収に一致している事を確認しよう。
<- model1$coefficients # 係数をオブジェクトに格納する
b0 <- matrix(c(rep(b0[1], 3), 0, b0[2:3], rep(b0[4], 3), 0, b0[5:6]), ncol=4)
b rownames(b) <- c("高校", "短大", "四大")
colnames(b) <- c("基準", "学歴", "女性", "女性×学歴")
# 係数行列から,基準値(高校―男性),学歴の主効果,性別の主効果,学歴×性別の交互作用効果を構成 b
基準 学歴 女性 女性×学歴
高校 462.7551 0.00000 -300.9495 0.0000000
短大 462.7551 61.31897 -300.9495 -79.0769085
四大 462.7551 195.97506 -300.9495 0.3589226
addmargins(b[, 1:2])[1:3,] # 男性の各カテゴリはこの様に計算する
基準 学歴 Sum
高校 462.7551 0.00000 462.7551
短大 462.7551 61.31897 524.0741
四大 462.7551 195.97506 658.7302
addmargins(b)[1:3,] # 女性の各カテゴリはこの様に計算する
基準 学歴 女性 女性×学歴 Sum
高校 462.7551 0.00000 -300.9495 0.0000000 161.8056
短大 462.7551 61.31897 -300.9495 -79.0769085 144.0476
四大 462.7551 195.97506 -300.9495 0.3589226 358.1395
以下の様にも計算出来る。この方がダミー変数を投入した重回帰分析の考え方をよく表現している。
sum(b0*c(1, 0, 0, 0, 0, 0)) # 男性―高校
[1] 462.7551
sum(b0*c(1, 1, 0, 0, 0, 0)) # 男性―短大・高専
[1] 524.0741
sum(b0*c(1, 0, 1, 0, 0, 0)) # 男性―四大
[1] 658.7302
sum(b0*c(1, 0, 0, 1, 0, 0)) # 女性―高校
[1] 161.8056
sum(b0*c(1, 1, 0, 1, 1, 0)) # 女性―短大・高専
[1] 144.0476
sum(b0*c(1, 0, 1, 1, 0, 1)) # 女性―四大
[1] 358.1395