处理异方差数据时,有许多选项可用。不幸的是,它们中的任何一个都不能保证始终有效。这是我熟悉的一些选项:
- 转变
- 韦尔奇方差分析
- 加权最小二乘
- 稳健回归
- 异方差一致性标准误
- 引导程序
- Kruskal-Wallis检验
- 有序逻辑回归
更新: 当您具有方差的异方差/异质性时,这是一些拟合线性模型的方式的演示R
(即ANOVA或回归)。
让我们开始看看您的数据。为了方便起见,我将它们加载到两个数据帧中,它们称为my.data
(结构如上,每组一列)和stacked.data
(具有两列:values
数字和ind
组指示符)。
我们可以使用Levene检验来正式测试异方差:
library(car)
leveneTest(values~ind, stacked.data)
# Levene's Test for Homogeneity of Variance (center = median)
# Df F value Pr(>F)
# group 2 8.1269 0.001153 **
# 38
当然,您具有异方差性。我们将检查各组的差异。经验法则是,线性模型对方差的异质性相当鲁棒,只要最大方差不大于最小方差的,因此我们也可以找到该比率: 4×
apply(my.data, 2, function(x){ var(x, na.rm=T) })
# A B C
# 0.01734578 0.33182844 0.06673060
var(my.data$B, na.rm=T) / var(my.data$A, na.rm=T)
# [1] 19.13021
你的变化很大不同,最大的,B
,是最小,。这是异性恋的一个有问题的水平。 19×A
你曾想过使用转换,如日志或平方根稳定方差。在某些情况下可以使用,但是Box-Cox类型转换通过不对称地挤压数据,以最高的数据挤压最多的方式向下挤压它们或以最低的数据挤压最多的方式向上挤压它们来稳定方差。因此,您需要数据的方差随均值而变化,以使其最佳工作。您的数据方差差异很大,但均值和中位数之间的差异相对较小,即分布大多重叠。作为教学练习,我们可以parallel.universe.data
通过在所有值上加上在值上加上来创建一些值2.7B
.7C
以显示其工作方式:
parallel.universe.data = with(my.data, data.frame(A=A, B=B+2.7, C=C+.7))
apply(parallel.universe.data, 2, function(x){ var(x, na.rm=T) })
# A B C
# 0.01734578 0.33182844 0.06673060
apply(log(parallel.universe.data), 2, function(x){ var(x, na.rm=T) })
# A B C
# 0.12750634 0.02631383 0.05240742
apply(sqrt(parallel.universe.data), 2, function(x){ var(x, na.rm=T) })
# A B C
# 0.01120956 0.02325107 0.01461479
var(sqrt(parallel.universe.data$B), na.rm=T) /
var(sqrt(parallel.universe.data$A), na.rm=T)
# [1] 2.074217
使用平方根变换可以很好地稳定这些数据。您可以在此处查看并行Universe数据的改进:
不仅仅是尝试不同的转换,更系统的方法是优化Box-Cox参数(尽管通常建议将其四舍五入到最接近的可解释转换)。在您的情况下,平方根或对数都是可以接受的,尽管实际上都无效。对于并行Universe数据,平方根最好: λλ=.5λ=0
boxcox(values~ind, data=stacked.data, na.action=na.omit)
boxcox(values~ind, data=stacked.pu.data, na.action=na.omit)
由于这种情况是ANOVA(即没有连续变量),因此处理异质性的一种方法是在检验(分数nb ,而不是)中对分母的自由度使用Welch校正: Fdf = 19.445
df = 38
oneway.test(values~ind, data=stacked.data, na.action=na.omit, var.equal=FALSE)
# One-way analysis of means (not assuming equal variances)
#
# data: values and ind
# F = 4.1769, num df = 2.000, denom df = 19.445, p-value = 0.03097
更通用的方法是使用加权最小二乘。由于某些组(B
)分布更多,因此与其他组中的数据相比,这些组中的数据提供的均值位置信息较少。通过为每个数据点提供权重,我们可以让模型将其合并。一个常见的系统是使用组方差的倒数作为权重:
wl = 1 / apply(my.data, 2, function(x){ var(x, na.rm=T) })
stacked.data$w = with(stacked.data, ifelse(ind=="A", wl[1],
ifelse(ind=="B", wl[2], wl[3])))
w.mod = lm(values~ind, stacked.data, na.action=na.omit, weights=w)
anova(w.mod)
# Response: values
# Df Sum Sq Mean Sq F value Pr(>F)
# ind 2 8.64 4.3201 4.3201 0.02039 *
# Residuals 38 38.00 1.0000
与未加权的方差分析(,)相比,这产生的和略有不同,但是很好地解决了异质性: Fp4.5089
0.01749
但是,加权最小二乘不是万能药。一个令人不安的事实是,只有权重正确才是正确的,这意味着,除其他外,这些权重是先验的。它也不能解决非正态(例如偏斜)或异常值。但是,使用从数据估算的权重通常会很好地工作,特别是如果您有足够的数据来以合理的精度估算方差(这类似于在有或时使用表而不是表的想法zt50100自由度),您的数据就足够正常,并且您似乎没有任何异常值。不幸的是,您的数据相对较少(每组13或15),有些偏斜,可能还有一些异常值。我不确定这些值是否足以造成很大的损失,但是您可以将加权最小二乘与稳健的方法混合使用。您可以使用四分位间距的倒数(不受每组中多达50%的离群值的影响),而不必使用方差作为散布的度量值(对离群值敏感,尤其是在低的情况下比较敏感)。然后,可以使用不同的损失函数(如Tukey的bisquare)将这些权重与稳健的回归相结合: N
1 / apply(my.data, 2, function(x){ var(x, na.rm=T) })
# A B C
# 57.650907 3.013606 14.985628
1 / apply(my.data, 2, function(x){ IQR(x, na.rm=T) })
# A B C
# 9.661836 1.291990 4.878049
rw = 1 / apply(my.data, 2, function(x){ IQR(x, na.rm=T) })
stacked.data$rw = with(stacked.data, ifelse(ind=="A", rw[1],
ifelse(ind=="B", rw[2], rw[3])))
library(robustbase)
w.r.mod = lmrob(values~ind, stacked.data, na.action=na.omit, weights=rw)
anova(w.r.mod, lmrob(values~1,stacked.data,na.action=na.omit,weights=rw), test="Wald")
# Robust Wald Test Table
#
# Model 1: values ~ ind
# Model 2: values ~ 1
# Largest model fitted by lmrob(), i.e. SM
#
# pseudoDf Test.Stat Df Pr(>chisq)
# 1 38
# 2 40 6.6016 2 0.03685 *
这里的权重并不是那么极端。预测组的装置稍有不同(A
:WLS 0.36673
,鲁棒0.35722
; B
:WLS 0.77646
,健壮0.70433
; C
:WLS 0.50554
,鲁棒0.51845
)中,用的装置B
和C
通过极值被较少拉动。
在计量经济学中,Huber-White(“三明治”)标准误差非常普遍。像Welch校正一样,这不需要您先验方差,也不需要您根据数据和/或可能不正确的模型估算权重。另一方面,我不知道如何将其与方差分析相结合,这意味着您只能将它们用于单个伪代码的测试,这使我在这种情况下不太有用,但无论如何我将向他们展示:
library(sandwich)
mod = lm(values~ind, stacked.data, na.action=na.omit)
sqrt(diag(vcovHC(mod)))
# (Intercept) indB indC
# 0.03519921 0.16997457 0.08246131
2*(1-pt(coef(mod) / sqrt(diag(vcovHC(mod))), df=38))
# (Intercept) indB indC
# 1.078249e-12 2.087484e-02 1.005212e-01
该函数vcovHC
为您的beta(您的虚拟代码)计算一个异方差一致的方差-协方差矩阵,这就是函数调用中的字母所代表的含义。要获取标准误差,请提取主对角线并取平方根。要获得Beta的检验,请将系数估算值除以SE,然后将结果与适当的(即带有剩余自由度的)进行比较。 ttt
对于R
特定的用户,@ TomWenseleers在下面的注释中指出,程序包中的?Anova函数car
可以接受white.adjust
参数,以使用异方差一致错误获取因子的值。 p
Anova(mod, white.adjust=TRUE)
# Analysis of Deviance Table (Type II tests)
#
# Response: values
# Df F Pr(>F)
# ind 2 3.9946 0.02663 *
# Residuals 38
# ---
# Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
您可以尝试通过自举来获得对测试统计量的实际抽样分布情况的经验估计。首先,通过使所有组均值完全相等来创建一个真正的null。然后,用替换进行重新采样,并在每个引导样本上计算测试统计量(),以得到在数据为零的情况下的抽样分布的经验估计,无论其状态是正常还是均匀。值等于或大于观察到的检验统计量的抽样分布比例是值: FFp
mod = lm(values~ind, stacked.data, na.action=na.omit)
F.stat = anova(mod)[1,4]
# create null version of the data
nullA = my.data$A - mean(my.data$A)
nullB = my.data$B - mean(my.data$B, na.rm=T)
nullC = my.data$C - mean(my.data$C, na.rm=T)
set.seed(1)
F.vect = vector(length=10000)
for(i in 1:10000){
A = sample(na.omit(nullA), 15, replace=T)
B = sample(na.omit(nullB), 13, replace=T)
C = sample(na.omit(nullC), 13, replace=T)
boot.dat = stack(list(A=A, B=B, C=C))
boot.mod = lm(values~ind, boot.dat)
F.vect[i] = anova(boot.mod)[1,4]
}
1-mean(F.stat>F.vect)
# [1] 0.0485
在某些方面,自举是进行参数(例如均值)分析的最终简化假设方法,但它确实假设您的数据很好地代表了总体,这意味着您拥有合理的样本量。由于您的很小,因此可能不太值得信赖。针对非正态性和异质性的最终保护措施可能是使用非参数检验。方差分析的基本非参数版本是Kruskal-Wallis检验: n
kruskal.test(values~ind, stacked.data, na.action=na.omit)
# Kruskal-Wallis rank sum test
#
# data: values by ind
# Kruskal-Wallis chi-squared = 5.7705, df = 2, p-value = 0.05584
尽管Kruskal-Wallis检验绝对是抵御I型错误的最佳方法,但它只能与单个类别变量一起使用(即,没有连续的预测变量或阶乘设计),并且在所讨论的所有策略中作用最小。另一种非参数方法是使用有序逻辑回归。这对很多人来说似乎很奇怪,但是您只需要假设您的响应数据包含合法的序数信息,他们肯定会这样做,否则上述其他所有策略也都无效:
library(rms)
olr.mod = orm(values~ind, stacked.data)
olr.mod
# Model Likelihood Discrimination Rank Discrim.
# Ratio Test Indexes Indexes
# Obs 41 LR chi2 6.63 R2 0.149 rho 0.365
# Unique Y 41 d.f. 2 g 0.829
# Median Y 0.432 Pr(> chi2) 0.0363 gr 2.292
# max |deriv| 2e-04 Score chi2 6.48 |Pr(Y>=median)-0.5| 0.179
# Pr(> chi2) 0.0391
从输出中可能不清楚,但是整个模型的测试(在本例中是您组的测试)是chi2
under Discrimination Indexes
。列出了两个版本,似然比测试和得分测试。似然比测试通常被认为是最好的。产生一个值。 p0.0363