在简单的线性模型(例如,单向或双向方差分析模型)中处理异方差实际上并不是很困难。
ANOVA 的稳健性
首先,正如其他人所指出的那样,ANOVA 对于与等方差假设的偏差具有惊人的鲁棒性,特别是如果您有大致平衡的数据(每组中的观察数量相等)。另一方面,等方差的初步测试则不是(尽管 Levene 的测试比教科书中通常教授的F测试要好得多)。正如乔治·博克斯所说:
对方差进行初步测试,就像乘划艇出海,看看情况是否足够平静,可以让一艘远洋客轮离开港口!
尽管 ANOVA 非常稳健,因为很容易考虑异方差性,但没有理由不这样做。
非参数检验
如果您真的对均值的差异感兴趣,那么非参数检验(例如,Kruskal-Wallis 检验)实际上没有任何用处。他们确实测试了组间的差异,但他们通常不测试均值的差异。
示例数据
让我们生成一个简单的数据示例,其中希望使用方差分析,但方差相等的假设不成立。
set.seed(1232)
pop = data.frame(group=c("A","B","C"),
mean=c(1,2,5),
sd=c(1,3,4))
d = do.call(rbind, rep(list(pop),13))
d$x = rnorm(nrow(d), d$mean, d$sd)
我们分为三组,均值和方差都有(明显)差异:
stripchart(x ~ group, data=d)

方差分析
毫不奇怪,普通的 ANOVA 可以很好地处理这个问题:
> mod.aov = aov(x ~ group, data=d)
> summary(mod.aov)
Df Sum Sq Mean Sq F value Pr(>F)
group 2 199.4 99.69 13.01 5.6e-05 ***
Residuals 36 275.9 7.66
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
那么,哪些群体不同呢?让我们使用 Tukey 的 HSD 方法:
> TukeyHSD(mod.aov)
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = x ~ group, data = d)
$group
diff lwr upr p adj
B-A 1.736692 -0.9173128 4.390698 0.2589215
C-A 5.422838 2.7688327 8.076843 0.0000447
C-B 3.686146 1.0321403 6.340151 0.0046867
P值为 0.26,我们不能声称 A 组和 B 组之间有任何差异(均值)。即使我们不考虑我们进行了三次比较,我们也不会得到低P -值(P = 0.12):
> summary.lm(mod.aov)
[…]
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.5098 0.7678 0.664 0.511
groupB 1.7367 1.0858 1.599 0.118
groupC 5.4228 1.0858 4.994 0.0000153 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.768 on 36 degrees of freedom
这是为什么?根据情节,有一个非常明显的区别。原因是方差分析假设每组的方差相等,并估计一个共同的标准差为 2.77(在summary.lm
表中显示为“残差标准误差”,或者您可以通过取残差均方 (7.66) 的平方根得到它)在 ANOVA 表中)。
但是 A 组的(总体)标准差为 1,而这个 2.77 的高估使得(不必要地)难以获得具有统计意义的结果,即,我们有一个(太)低功效的检验。
方差不等的“方差分析”
那么,如何拟合一个合适的模型,一个考虑到方差差异的模型呢?在 R 中很容易:
> oneway.test(x ~ group, data=d, var.equal=FALSE)
One-way analysis of means (not assuming equal variances)
data: x and group
F = 12.7127, num df = 2.000, denom df = 19.055, p-value = 0.0003107
因此,如果您想在 R 中运行简单的单向“ANOVA”而不假设方差相等,请使用此函数。它基本上是 (Welch) 的扩展,t.test()
适用于两个方差不等的样本。
不幸的是,它不适用于TukeyHSD()
(或您在对象上使用的大多数其他功能aov
),因此即使我们非常确定存在组差异,我们也不知道它们在哪里。
建模异方差
最好的解决方案是显式地对方差建模。在 R 中这很容易:
> library(nlme)
> mod.gls = gls(x ~ group, data=d,
weights=varIdent(form= ~ 1 | group))
> anova(mod.gls)
Denom. DF: 36
numDF F-value p-value
(Intercept) 1 16.57316 0.0002
group 2 13.15743 0.0001
当然,仍然存在显着差异。但是现在 A 组和 B 组之间的差异也变得静态显着(P = 0.025):
> summary(mod.gls)
Generalized least squares fit by REML
Model: x ~ group
[…]
Variance function:
Structure: Different standard
deviations per stratum
Formula: ~1 | group
Parameter estimates:
A B C
1.000000 2.444532 3.913382
Coefficients:
Value Std.Error t-value p-value
(Intercept) 0.509768 0.2816667 1.809829 0.0787
groupB 1.736692 0.7439273 2.334492 0.0253
groupC 5.422838 1.1376880 4.766542 0.0000
[…]
Residual standard error: 1.015564
Degrees of freedom: 39 total; 36 residual
因此,使用合适的模型会有所帮助!另请注意,我们得到了(相对)标准偏差的估计值。可以在结果的底部找到 A 组的估计标准偏差 1.02。B 组的估计标准差是该值的 2.44 倍,即 2.48,C 组的估计标准差同样为 3.97(键入intervals(mod.gls)
以获取 B 组和 C 组的相对标准差的置信区间)。
校正多个测试
但是,我们确实应该纠正多次测试。这很容易使用“multcomp”库。不幸的是,它没有对“gls”对象的内置支持,所以我们必须先添加一些辅助函数:
model.matrix.gls <- function(object, ...)
model.matrix(terms(object), data = getData(object), ...)
model.frame.gls <- function(object, ...)
model.frame(formula(object), data = getData(object), ...)
terms.gls <- function(object, ...)
terms(model.frame(object),...)
现在让我们开始工作:
> library(multcomp)
> mod.gls.mc = glht(mod.gls, linfct = mcp(group = "Tukey"))
> summary(mod.gls.mc)
[…]
Linear Hypotheses:
Estimate Std. Error z value Pr(>|z|)
B - A == 0 1.7367 0.7439 2.334 0.0480 *
C - A == 0 5.4228 1.1377 4.767 <0.001 ***
C - B == 0 3.6861 1.2996 2.836 0.0118 *
A组和B组之间仍有统计学差异!☺ 我们甚至可以获得(同时)组均值差异的置信区间:
> confint(mod.gls.mc)
[…]
Linear Hypotheses:
Estimate lwr upr
B - A == 0 1.73669 0.01014 3.46324
C - A == 0 5.42284 2.78242 8.06325
C - B == 0 3.68615 0.66984 6.70245
使用近似(这里完全)正确的模型,我们可以相信这些结果!
请注意,对于这个简单的示例,C 组的数据并没有真正添加关于 A 组和 B 组之间差异的任何信息,因为我们对每个组的单独均值和标准差都进行了建模。我们可以只使用成对的t检验校正多重比较:
> pairwise.t.test(d$x, d$group, pool.sd=FALSE)
Pairwise comparisons using t tests with non-pooled SD
data: d$x and d$group
A B
B 0.03301 -
C 0.00098 0.02032
P value adjustment method: holm
然而,对于更复杂的模型,例如双向模型或具有许多预测变量的线性模型,使用 GLS(广义最小二乘法)和显式建模方差函数是最佳解决方案。
并且方差函数不必简单地是每组中不同的常数;我们可以对其施加结构。例如,我们可以将方差建模为每组均值的幂(因此只需要估计一个参数,即指数),或者可能是模型中预测变量之一的对数。gls()
使用 GLS(以及在 R 中),所有这些都非常容易。
广义最小二乘法是恕我直言,一种未被充分利用的统计建模技术。不必担心与模型假设的偏差,而是对这些偏差进行建模!