两种使用自举测试两个样本均值差异的方法

机器算法验证 假设检验 t检验 引导程序
2022-04-07 07:12:26

我想引导测试一个假设(两个样本学生 t 检验)。在 Efron 和 Tibshirani 1993 p.224 中有明确的代码:对于每个观察,减去其组平均值并添加整体平均值,其中整体平均值是组合样本的平均值。他们声称我们应该在零假设下引导分布,这就是我们应该这样做的原因。

但是,我还了解到,可以直接从样本引导而无需修改它们。我尝试了两种方法:Efron 的步骤(使用 function boot_t_F)以及不转换观察结果(使用 function boot_t_B)。

由此产生的自举 p 值(作为超过原始测试统计量的自举测试统计量的比例)应该完全相同,但事实并非如此。

为什么是这样?

我的两个功能如下:

 boot_t_B<-function(x,y){
  print(t.test(x, y, var.equal=TRUE)) #original test statistics
  t.est<-abs(t.test(x, y, var.equal=TRUE)$statistic) #Student's t-test

  grand_mean<-mean(c(x,y), na.rm=T) #global mean
  x1<-x #-mean(x, na.rm=T)+grand_mean it's not subtracted/added here
  y1<-y #-mean(y, na.rm=T)+grand_mean

  B      <- 10000 #number of bootstrap samples
  t.vect <- vector(length=B) #vector for bootstrapped t-statistics
  for(i in 1:B){
    boot.c <- sample(x1, size=length(x), replace=T)
    boot.p <- sample(y1, size=length(y), replace=T)
    t.vect[i] <- t.test(boot.c, boot.p, var.equal=TRUE)$statistic
  }
   return(mean(t.vect>t.est)) #bootstrapped p-value
} 


boot_t_F<-function(x,y){
  print(t.test(x, y, var.equal=TRUE)) #original test statistics
  t.est<-abs(t.test(x, y, var.equal=TRUE)$statistic) #Student's t-test

  grand_mean<-mean(c(x,y), na.rm=T) #global mean
  x1<-x-mean(x, na.rm=T)+grand_mean
  y1<-y-mean(y, na.rm=T)+grand_mean

  B      <- 10000 #number of bootstrap samples
  t.vect <- vector(length=B) #vector for bootstrapped test-statistics
  for(i in 1:B){
    boot.c <- sample(x1, size=length(x), replace=T)
    boot.p <- sample(y1, size=length(y), replace=T)
    t.vect[i] <- t.test(boot.c, boot.p, var.equal=TRUE)$statistic
  }

  return(mean(t.vect>t.est)) #bootstrapped p-value
} 

set.seed(1678)
boot_t_B(rnorm(25,0,10), rnorm(25,5,10))
[1] 4e-04
set.seed(1678)
boot_t_F(rnorm(25,0,10), rnorm(25,5,10))
[1] 0.0507

注意:我“随机”选择了样本的(正态)分布。

2个回答

问题是您的引导程序boot_t_B没有正确完成。如果您没有将均值校正为相同(即,通过重新居中每个样本来强制原假设为真),则通过从两个样本组合中采样来强制原假设为真:

boot.c <- sample(c(x1,y1), size=length(x), replace=T)
boot.p <- sample(c(x1,y1), size=length(y), replace=T)

这样做的原因是,如果平均值不同,在您的原始公式中boot.c并且boot.p实际上是来自替代假设的样本,其中替代分布“以数据为中心”。您可以将其视为最有可能给定数据的替代分布的引导抽样,只是您是非参数的,而不是使用参数引导。因此,您不会得到 p 值,这当然是在假设零假设的情况下计算出来的。

如果你这样做,你会得到:

> set.seed(1678)
> boot_t_B(rnorm(25,0,10), rnorm(25,5,10))
[1] 0.05
> set.seed(1678)
> boot_t_F(rnorm(25,0,10), rnorm(25,5,10))
[1] 0.0507

添加到@jbowman -test的引导程序,您可以考虑在这种情况下使用的置换测试(例如,查看Phillip I. Good ,或该作者关于此主题的其他书籍)。为了进行置换测试,我们假设在零分布下,所有值都在组之间随机重新分布,因此置换过程将是随机重新分配组标签。您必须从船体分布中采样,这可以通过重新分配组标签来实现,或者通过 Efron 和 Tibshirani 建议的减去组均值来实现。t

perm_test <- function(x, y) {

  B <- 10000
  nx <- length(x)
  ny <- length(y)
  N <- nx+ny
  xy <- c(x, y)
  orig <- mean(x) - mean(y)
  res <- numeric(B)

  for (i in 1:B) {
    idx <- sample(N, nx)
    tmpx <- xy[idx]
    tmpy <- xy[-idx]
    res[i] <- mean(tmpx) - mean(tmpy)
  }

  mean(orig > res)

}

结果类似于“正确的”引导程序,或者按照@jbowman的建议使用:

> set.seed(1678)
> perm_test(rnorm(25,0,10), rnorm(25,5,10))
[1] 0.051