【通俗向】⽅差分析--⼏种常见的⽅差分析
上⼀篇⽂章说了⽅差和t检验的差异,这篇说说⼏种实⽤的⽅差分析⽅法和R语⾔实现。
⼀般情况下,基本的⽅差分析模型包含以下三类,三类下⾯会根据具体情况再进⾏细分,主要的三类为⼀元⽅差分析,协⽅差分析,多元⽅差分析。
1、⼀元⽅差分析
⼀元⽅差分为单因素、多因素两类(协⽅差单独分类),既然⽅差是检验各组差异的,那么从⼀个最简单的例⼦⼊⼿,探寻各类⽅差分析的适⽤条件和特点。
OK,正题开始,鉴于⾃⼰也算是酷爱篮球,就举个篮球运动员的例⼦吧,以下数据纯属瞎编,如有雷同纯属巧合。
有⼀天,詹姆斯和科⽐遇见了,鉴于科⽐已经退役,詹姆斯说⽼科,我们⽐投篮吧,看看是你厉害还是我厉害。科⽐⼀听这话顿时来了精神,就在我家球场,放学别⾛。
詹姆斯说,我的投篮命中率应该⽐你⾼,但是为了避免你蒙进去的多,我们⽐试5组,每⼀组投10次,看谁进的多,科⽐:Deal!
下⾯是相关代码
name<-c(rep('Kobe',5),rep('James',5))
good<-c(5,4,6,5,7,7,5,6,4,8)
a<-data.frame(name,good)
fit1<-aov(good~name,a)
summary(fit1)
其中建⽴了⼀个数据框:a,也就是两个⼈的投篮⽐较:
name good
1  Kobe    5
2  Kobe    4
3  Kobe    6
4  Kobe    5
5  Kobe    7
6  James    7
7  James    5
8  James    6
9  James    4
10 James    8
结果如下:
Df Sum Sq Mean Sq F value Pr(>F)
name        10.90.90.4740.511
Residuals    815.2  1.9
可以看到,p=0.511,也就是说,⼆者的投篮没有显著差异(同样可以使⽤t检验)。
这时候,乔丹⽼流氓来了,看到他们在⽐投篮,说,要不我也参与下,好久没活动了。
随着⽼流氓的连续空⼼,科⽐和詹姆斯马上就要报警了,最后看看三⼈的命中数:
b<-rbind(a,data.frame(name=rep('jordan',5),good=c(10,9,10,10,10)))
name good高云翔怎么了
1    Kobe    5
2    Kobe    4
3    Kobe    6
王力宏是双性恋吗
4    Kobe    5
5    Kobe    7
6  James    7
7  James    5
8  James    6
9  James    4
10  James    8
11 jordan  10
12 jordan    9
13 jordan  10
14 jordan  10
15 jordan  10
接下来就做⼀个t检验做不了的事情:两组以上的⽅差分析:
fit2<-aov(good~name,b)
summary(fit2)
结果是:
Df Sum Sq Mean Sq F value  Pr(>F)
name        2  56.93  28.467  21.35 0.000111 ***
Residuals  12  16.00  1.333
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
汪小菲删光大S动态疑离婚我们看到P值是0.000111,也就是超级显著了,但是我们知道三者有显著差别,但是谁和谁有显著差别暂时还不知道(虽然能猜到,但还是装不知道),这时候需要借助Tukey或Duncan⽅法进⾏检验下,这⾥先使⽤Tukey⽅法检测:
1升油等于多少斤TukeyHSD(fit2)
结果为
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = good ~ name, data = b)
$name
diff      lwr      upr    p adj
Kobe-James  -0.6 -2.5483321.3483320.6973146
jordan-James3.81.8516685.7483320.0005973
jordan-Kobe  4.42.4516686.3483320.0001637
可以看到,Kobe和James没有差异,乔⽼爷⼦和两个⼈都有差异,但是和Kobe差异最⼤,这个⽤图形表⽰就是
plot(TukeyHSD(fit2))
图形中纵轴是均值的差异,包含0说明差异不明显,不包含0说明差异明显,可以看到乔丹的均值⽐詹姆斯和科⽐都⼤很多。
那么这个结果说明了乔丹⽐科⽐和詹姆斯投篮准,最后还需要进⾏正态性假设,因为我们需要知道这5组投篮是随机从他们职业⽣涯的千千万万个投篮中抽取的,这⾥需要检测下残差是否符合正态分布。
到这⾥说的有点远,因为残差需要进⾏线性拟合,但是有三个因素性变量,但是我不能把名字作为横轴吧,那么乔丹=?科⽐=?,⼀般在这种情况下处理就是两两⽐较,⽐如把詹姆斯的投篮命中作为因变量,乔丹作为⾃变量1,科⽐作为⾃变量2,那么其实舍弃了科⽐和乔丹的⽐较,⽐如载⼊car包中,看具体的因⼦编码:
library(car)
contrasts(b$name)
结果:
Kobe jordan
James    0      0
Kobe      1      0
jordan    0      1
可以看到james都是0,也就是因变量,然后Kobe是1,然后乔丹是1,也就是先拿科⽐作为1,然后保
持科⽐不变,拿乔丹作为1,看和詹姆斯命中的影响,既然看残差符合正态分布,所以可以通过两个⽅式看qq图或正态性检测,先看第⼀个qqplot:
fit2.1<-lm(good~name,b)
summary(fit2.1)
qqPlot(fit2.1)
先看看fit2.1的情况:
可以看到,namejordan那⼀列的p值是0.000221,说明保持科⽐不变的前提下⼆者有显著性差异,但是反⽽科⽐和詹姆斯没啥差异
(p=0.427336)。然后看看qq图:
所有残差都在两个红虚线,95%置信区间内,如果不放⼼,我们再⽤第⼆种正态检测下,并画出图看看。
第⼀个就是shapiro正态性检测,结果为看到,有0.9323的概率是正态分布。然后看密度图:
Call:
毕业生祝福语lm(formula = good ~ name, data = b)
Residuals:
Min    1Q Median    3Q    Max
-2.0  -0.6    0.2    0.4    2.0
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept)  6.0000    0.5164  11.619 6.92e-08 ***
nameKobe    -0.6000    0.7303  -0.822 0.427336
namejordan    3.8000    0.7303  5.203 0.000221 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.155 on 12 degrees of freedom
Multiple R-squared:  0.7806,    Adjusted R-squared:  0.7441 F-statistic: 21.35 on 2 and 12 DF,  p-value: 0.0001115
shapiro .test (rstudent(fit2.1))
Shapiro-Wilk normality test
data :  rstudent(fit2.1)
W = 0.97576, p-value = 0.9323
plot(density(rstudent(fit2.1)))
⽐较符合正态分布。
本来想只说说单因素⽅差分析的,结果说了这么多。
下⾯继续刚才的话题,刚才乔丹加⼊了,我们看到三个⼈的投篮命中数:
name good
1    Kobe    5
2    Kobe    4
3    Kobe    6
4    Kobe    5
5    Kobe    7
6  James    7
7  James    5
8  James    6
9  James    4
10  James    8
11 jordan  10
12 jordan    9
13 jordan  10陈紫函戴向宇
14 jordan  10
15 jordan  10
到现在为⽌,都是单因素⽅差分析,下⾯看看双因素分析;
詹姆斯和科⽐在看了这篇⽂章之后,觉得⽼流氓简直太厉害了,但是詹姆斯不服科⽐,我应该⽐你投篮准,但是因为这是你家后院,你家后院篮球场场地不好太晃眼,我们三个在每个⼈家的篮球场⽐⽐怎么样?
⽼流氓⾃然⽆所谓,科⽐倒是也觉得这样公平,那么把三个场地的每个⼈的投篮命中个数都统计下:
b1<-c(5,4,3,7,5,8,8,9,7,8,9,9,9,7,8)
b2<-c(6,6,7,6,7,8,7,6,7,8,9,10,10,8,9)
c<-cbind(b,b1,b2)
colnames(c)<-c('name','count.J','count.K','count.j')
library(reshape2)
d<-melt(c,variable_name = 'count')
d数据框就是整形好的数据: