R语言——方差分析

一、方差分析的基本概念

方差分析是在20世纪20年代发展起来的一种统计方法,它是由英国统计学家费希尔在进行实验设计时为解释实验数据而首先引入的。

从形式上看,方差分析是比较多个总体的均值是否相等;但是其本质上是研究变量之间的相互关系。方差分析主要用于研究一个数值因变量与一个或多个分类自变量的关系。

根据方差分析的计算方法给方差分析下一个定义:

方差分析(analysis of variance ,ANOVA)就是通过检验各总体的均值是否相等来判断分类型自变量对数值型因变量是否有显著影响。

二、利用实例讲解方差分析的应用

假设某私立学校具有小学、初中、高中三个水平的学生,每个水平阶段的学生每个学期都会进行一次期末考试。另外假设小学共抽取10个班级,初中抽取9个班级,高中抽取8个班级。

每个班级期末考试的平均分分别用Ai(i=1,2,...,10)、Bj(j=1,2,...,9)和Ck(k=1,2,...,8)表示,为了比较各个水平阶段的班级平均分是否有显著性差异,就可以使用方差分析。

这里的阶段就是因素,也称之为因子,因子的三个取值:小学、初中、高中,称为水平或处理。

 

阶段

 

小学

初中

高中

1

90

87

80

2

90

88

79

3

89

90

80

4

88

78

89

5

89

89

87

6

91

90

86

7

96

80

89

8

88

81

83

9

80

82

 

10

90

 

 

为了更为直观地观察各水平平均值,绘制箱线图如下:

 R语言——方差分析_第1张图片

由于以上数据只涉及到一个分类自变量,即阶段,因此属于单因素方差分析。

从箱线图可以看出,各水平学生的平均分存在一定的差异,但是这种差异显著不显著,还需要进一步分析。

同时,各个水平的方差看起来也不尽相同。

二、方差分析的基本思想

由以上分析可以看出,虽然各个水平的学生平均分存在差异,但是其方差也有差别,方差分析的基本思想就是弄清楚影响因变量取值的误差来源,以判断是否是分类自变量对因变量产生影响。

在上述数据中,各组数据的误差主要来源于以下几个部分。

首先,即使是同一组的数据,其取值也具有差别,这是因为班级是随机抽取的,因此他们之间的差异可以看作是随机因素的影响造成的,或者说是由抽样的随机性造成的,这种来自水平内部的误差称之为组内误差,显然,组内误差只含有随机误差。

其次,各组的取值不同。来自不同水平之间的误差称为组间误差,这种差异可能来自于随机误差,也可能来自于因子本身的系统性误差造成的系统误差。因此,组内误差包含有可能包含两个方面,即随机误差和系统误差。

最后,总误差为组内误差与组间误差之和。

这样,就把造成因变量的差异的误差分解成组内误差和组间误差。

总误差=组内误差+组间误差

如果组内误差与组间误差相差太大,说明组间误差存在很大成分的系统误差,这时候就可以认为各水平均值显著不等。

将组间误差与总误差的比值定义为关系强度R2,即

R2=

将各平方和除以对应的自由度,则得到相应的均方,也称为方差。

SST的自由度为n-1

SSA的自由度为k-1

SSE的自由度为n-k

R语言——方差分析_第2张图片

三、方差分析的基本假设

(1)各总体的方差必须相等

(2)各总体必须服从正态分布

(3)各观测值相互独立

四、方差分析的类型

根据影响因变量的因素个数,可以把方差分析分为单因素方差分析和双因素方差分析。

如果是双因素方差分析,根据两个因素的交互作为是否对因变量产生影响可分为无交互作用的双因素方差分析和有交互作用的双因素方差分析。

五、方差分析的R语言实现

(一)方差分析基本假设的检验

将数据在R语言中以列表形式存储,

> ave_score

$primary

 [1] 90 90 89 88 89 91 96 88 80 90

 

$junior

[1] 87 88 90 78 89 90 80 81 82

 

$senior

[1] 80 79 80 89 87 86 89 83

1、方差齐性检验

(1)Bartlett检验(Bartlett检验也可以接受一个数据框为输入,结构与下面的Levene检验相同。此方法比较适合用于总体服从正态分布的检验)

> bartlett.test(ave_score)

 

         Bartlett test of homogeneity of variances

 

data:  ave_score

Bartlett's K-squared = 0.28233, df = 2, p-value = 0.8683

P值为0.8683,由于p大于常用的a=0.05,因此,无法拒绝原假设,即认为方差相等。

(2)Levene检验 (Levene检验函数接受的数据结构为数据框结构,并且一列是各水平的取值score,另一列是所属的水平level,用score~level表示score为因变量,level为自变量。此方法适用于总体非正态的检验)

> scores<-data.frame(score=c(ave_score$primary,ave_score$junior,ave_score$senior),level=rep(c("primary","junior","senior"),c(10,9,8)))

> scores

   score   level

1     90  primary

2     90  primary

3     89  primary

4     88  primary

5     89  primary

6     91  primary

7     96  primary

8     88  primary

9     80  primary

10    90  primary

11    87  junior

12    88  junior

13    90  junior

14    78  junior

15    89  junior

16    90  junior

17    80  junior

18    81  junior

19    82  junior

20    80  senior

21    79  senior

22    80  senior

23    89  senior

24    87  senior

25    86  senior

26    89  senior

27    83  senior

> leveneTest(score~level,data = scores)

Levene's Test for Homogeneity of Variance (center = median)

      Df F value Pr(>F)

group  2  1.0461 0.3668

      24              

P值大于0.05,可认为等方差

(3)Fligner-Killeen检验

> fligner.test(ave_score)(fliger.test函数可以接受列表输入)

 

         Fligner-Killeen test of homogeneity of variances

 

data:  ave_score

Fligner-Killeen:med chi-squared = 2.0447, df = 2, p-value = 0.3597

结论同上

2、正态性检验

shapiro检验(输入数据为一个向量,检验该向量的数据是否服从正态分布)

> sapply(ave_score,shapiro.test)(

          primary                       junior                      

statistic 0.8332102                     0.8725879                   

p.value   0.03657401                    0.1310428                   

method    "Shapiro-Wilk normality test" "Shapiro-Wilk normality test"

data.name "X[[i]]"                      "X[[i]]"                     

          senior                      

statistic 0.8764152                   

p.value   0.1739798                   

method    "Shapiro-Wilk normality test"

data.name "X[[i]]"   

primary 水平的检验拒绝原假设,即非正态。这个数据只是为了说明方差分析的原理,并没有进行严格的验证,但是不影响后续工作的推进。

3、独立性检验

可以通过控制抽样过程来控制独立性,无具体的检验方法。

(二)方差分析

1、单因素方差分析

方差分析所需的数据结构一般是一个数据框,就像上面的那样。

进行方差分析可以使用lm()函数,也可以使用aov()函数,再利用summary()函数或者anova()函数输出最终结果。

对于上述的单因素方差分析,分别用这两者方法分析如下:

(1)用lm()函数

> score_lm<-lm(score~level,data = scores)

> summary(score_lm)

 

Call:

lm(formula = score ~ level, data = scores)

 

Residuals:

   Min     1Q Median     3Q    Max

-9.100 -3.500  0.900  2.938  6.900

 

Coefficients:

             Estimate Std. Error t value Pr(>|t|)   

(Intercept)    85.000      1.424  59.706   <2e-16 ***

levelprimaty    4.100      1.962   2.089   0.0475 * 

levelsenior    -0.875      2.075  -0.422   0.6770   

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

 

Residual standard error: 4.271 on 24 degrees of freedom

Multiple R-squared:  0.2309,         Adjusted R-squared:  0.1668

F-statistic: 3.602 on 2 and 24 DF,  p-value: 0.04285

 

> anova(score_lm)

Analysis of Variance Table

 

Response: score

          Df Sum Sq Mean Sq F value  Pr(>F) 

level      2 131.41  65.705  3.6021 0.04285 *

Residuals 24 437.78  18.241                 

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

 

Summary()函数会输出残差和模型,anova()只会输出结果。

(2)利用aov()函数

> score_aov<-aov(score~level,data = scores)

> summary(score_aov)

            Df Sum Sq Mean Sq F value Pr(>F) 

level        2  131.4   65.71   3.602 0.0429 *

Residuals   24  437.8   18.24                

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

> anova(score_aov)

Analysis of Variance Table

 

Response: score

          Df Sum Sq Mean Sq F value  Pr(>F) 

level      2 131.41  65.705  3.6021 0.04285 *

Residuals 24 437.78  18.241                 

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

从上述结果可以看出,anova()输出的是标准的方差分析表,而利用lm()函数计算的方差分析会输出回归模型,以及残差——更多的是回归的信息。

2、无交互作用的双因素方差分析

有的时候,因变量可能受到来自一个以上的因素的影响,最典型的就是双因素方差分析。假如因素A与因素B没有联合效应,则称为无交互作用的双因素方差分析。

考虑以下的例子,假如某经销商想知道一款饮料的销售额与销售地点和饮料包装风格的关系,探究这两个因素是否都在影响销售额或者只有一个因素影响销售额。

数据如下:

    地区
    A B C D E 合计
     包装 30 33 29 41 37 170
32 38 39 32 40 181
29 33 35 39 40 176
40 41 45 39 40 205
合计 131 145 148 151 157 732

无交互作用的双因素方差分析与单因素方差分析类似,只是在写公式的时候变成【销售额~地区+包装】就行。

如果为了省事,可以使用gl()函数生成因子,但是为了与原数据对应,减小阅读压力,建议自己写因子水平。

gl(n, k, length = n*k, labels = seq_len(n), ordered = FALSE)
n:一个整数,表示水平的个数

an integer giving the number of levels.

k:表示每个水平重复几遍

an integer giving the number of replications.

length:如果前面两个都给出了,就不用给这项参数了,否则需要给出所有数据的个数

an integer giving the length of the result.

labels:结果的标签向量

an optional vector of labels for the resulting factor levels.

ordered:是否排序

a logical indicating whether the result should be ordered or not.

 

这里,我选择自己手动生成水平数据。

> dat<-read.table("clipboard",header = TRUE,stringsAsFactors = FALSE)

> dat

  包装  A  B  C  D  E

1   甲 30 33 29 41 37

2   乙 32 38 39 32 40

3   丙 29 33 35 39 40

4   丁 40 41 45 39 40

 

> sales<-c(dat$A,dat$B,dat$C,dat$D,dat$E)

> areas<-rep(c("A","B","C","D","E"),each=4)

> style<-rep(c('甲','乙','丙','丁'),5)

 

> sales

 [1] 30 32 29 40 33 38 33 41 29 39 35 45 41 32 39 39 37 40 40 40

> areas

 [1] "A" "A" "A" "A" "B" "B" "B" "B" "C" "C" "C" "C" "D" "D" "D" "D" "E" "E" "E" "E"

> style

 [1] "甲" "乙" "丙" "丁" "甲" "乙" "丙" "丁" "甲" "乙" "丙" "丁" "甲" "乙" "丙" "丁"

[17] "甲" "乙" "丙" "丁"

 

> drink_sale<-data.frame(sales,areas,style)

> drink_sale

   sales areas style

1     30     A    甲

2     32     A    乙

3     29     A    丙

4     40     A    丁

5     33     B    甲

6     38     B    乙

7     33     B    丙

8     41     B    丁

9     29     C    甲

10    39     C    乙

11    35     C    丙

12    45     C    丁

13    41     D    甲

14    32     D    乙

15    39     D    丙

16    39     D    丁

17    37     E    甲

18    40     E    乙

19    40     E    丙

20    40     E    丁

分析之前需要对地区和包装风格做方差齐性检验。

> bartlett.test(sales~areas,data = drink_sale)

 

         Bartlett test of homogeneity of variances

 

data:  sales by areas

Bartlett's K-squared = 4.833, df = 4, p-value = 0.3049

> bartlett.test(sales~style,data = drink_sale)

         Bartlett test of homogeneity of variances

 

data:  sales by style

Bartlett's K-squared = 2.017, df = 3, p-value = 0.5689

检验结果都无法拒绝原假设,即可以认为方差是相等的。

 接下来进行方差分析

> drink_aov<-aov(sales~areas+style,data = drink_sale)

> anova(drink_aov)

Analysis of Variance Table

Response: sales

          Df Sum Sq Mean Sq F value  Pr(>F) 

areas      4   93.8  23.450  1.6572 0.22397 

style      3  141.2  47.067  3.3263 0.05655 .

Residuals 12  169.8  14.150                 

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

两个p值都是大于0.05,因此可以认为销售地区与包装风格对销售额没有显著影响。

3、有交互作用的双因素方差分析

因素之间的交互作用在现实中很常见,比如胖胖的人喜欢蓝色的衣服,南方的人更喜欢喝雪花啤酒等,前者是体重和颜色的交互作用,后者是地区和啤酒品牌的交互作用。

因此,如果两个因素联合在一起对因变量有显著的影响,则称这样的方差分析为有交互作用的方差分析。

下面的数据展示的是各个路段在高峰期与非高峰期的车流量(数据来自《数据分析:R语言实战》)。对其进行双因素方差分析的过程如下。

  路段1 路段2 路段3
高峰期 25 24 27 25 25 19 20 23 22 21  29 28 31 28 30
非高峰期 20 17 22 21 17 18 17 13 16 12 22 18 24 21 22

 

> cars<-read.table("clipboard",header = TRUE,stringsAsFactors = TRUE)

> summary(cars)

     车流量         路段          时期  

 Min.   :12.00   路段1:10   非高峰期:15 

 1st Qu.:18.25   路段2:10   高峰期  :15 

 Median :22.00   路段3:10               

 Mean   :21.90                          

 3rd Qu.:25.00                          

 Max.   :31.00      

方差齐性检验

> bartlett.test(车流量~路段,data=cars)

         Bartlett test of homogeneity of variances

 

data:  车流量 by 路段

Bartlett's K-squared = 0.57757, df = 2, p-value = 0.7492

 

> bartlett.test(车流量~时期,data=cars)

         Bartlett test of homogeneity of variances

 

data:  车流量 by 时期

Bartlett's K-squared = 0.053302, df = 1, p-value = 0.8174

上述检验显示满足方差齐性条件

接下来进行方差分析

> cars_aov<-aov(车流量~路段*时期,data=cars)

> anova(cars_aov)

Analysis of Variance Table

 

Response: 车流量

          Df  Sum Sq Mean Sq F value    Pr(>F)   

路段       2 261.600 130.800 35.3514 7.018e-08 ***

时期       1 313.633 313.633 84.7658 2.407e-09 ***

路段:时期  2   6.667   3.333  0.9009    0.4195   

Residuals 24  88.800   3.700                     

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

路段和时期的p值都显著小于0.05,但是二者的联合效应的p值为0.4195,大于0.05,因此可以认为二者无显著的交互作用。

 

交互效应图可以更加直观地看出两个因素是否具有交互效应,可以用interaction.plot()绘制

interaction.plot(x.factor, trace.factor, response, fun = mean,
                 type = c("l", "p", "b", "o", "c"), legend = TRUE,
                 trace.label = deparse(substitute(trace.factor)),
                 fixed = FALSE,
                 xlab = deparse(substitute(x.factor)),
                 ylab = ylabel,
                 ylim = range(cells, na.rm = TRUE),
                 lty = nc:1, col = 1, pch = c(1:9, 0, letters),
                 xpd = NULL, leg.bg = par("bg"), leg.bty = "n",
                 xtick = FALSE, xaxt = par("xaxt"), axes = TRUE,
                 ...)
x.factor

a factor whose levels will form the x axis.

trace.factor

another factor whose levels will form the traces.

response

a numeric variable giving the response

 
    

> names(cars)<-c("flow","path","time")

 
    

> attach(cars)

 
    

> interaction.plot(path,time,flow,legend = F)

> interaction.plot(time,path,flow,legend = F)


 两个图中的曲线均没有相交,可以初步认为没有交互作用。

你可能感兴趣的:(R语言——方差分析)