두 개의 독립적 그룹이있는 데이터가 있다고 가정하십시오.
g1.lengths <- c (112.64, 97.10, 84.18, 106.96, 98.42, 101.66)
g2.lengths <- c (84.44, 82.10, 83.26, 81.02, 81.86, 86.80,
85.84, 97.08, 79.64, 83.32, 91.04, 85.92,
73.52, 85.58, 97.70, 89.72, 88.92, 103.72,
105.02, 99.48, 89.50, 81.74)
group = rep (c ("g1", "g2"), c (length (g1.lengths), length (g2.lengths)))
lengths = data.frame( lengths = c(g1.lengths, g2.lengths), group)
g1에 6 개의 관측치가 있고 g2에 22 개의 관측치 가 있는 경우 그룹당 샘플 크기가 바이어스 됨이 분명합니다 . 전통적인 분산 분석은 임계 값이 0.05 (p 값은 0.0044 )로 설정 될 때 그룹마다 다른 평균을 갖도록 제안합니다 .
summary (aov (lengths~group, data = lengths))
저의 목표는 평균 차이를 비교하는 것이므로 이러한 불균형 및 작은 표본 데이터는 전통적인 접근 방식으로 부적절한 결과를 제공 할 수 있습니다. 따라서 순열 테스트와 부트 스트랩을 수행하고 싶습니다.
퍼미션 테스트
귀무 가설 (H0)은 그룹의 평균이 동일하다는 것을 나타냅니다. 순열 테스트에서 이러한 가정은 그룹을 하나의 샘플로 풀링하여 정당화됩니다. 이렇게하면 두 그룹에 대한 표본이 동일한 분포에서 추출됩니다. 풀링 된 데이터에서 반복 샘플링 (또는보다 정확하게-셔플 링)을 수행하면 새로운 방식으로 관측치가 샘플에 재 할당 (셔플)되고 테스트 통계가 계산됩니다. 이 n 번 수행하면 H0이 참인 가정하에 테스트 통계의 샘플링 분포가 제공됩니다. 마지막으로, H0 하에서 p 값은 검정 통계량이 관측 값과 같거나이를 초과 할 확률입니다.
s.size.g1 <- length (g1.lengths)
s.size.g2 <- length (g2.lengths)
pool <- lengths$lengths
obs.diff.p <- mean (g1.lengths) - mean (g2.lengths)
iterations <- 10000
sampl.dist.p <- NULL
set.seed (5)
for (i in 1 : iterations) {
resample <- sample (c(1:length (pool)), length(pool))
g1.perm = pool[resample][1 : s.size.g1]
g2.perm = pool[resample][(s.size.g1+1) : length(pool)]
sampl.dist.p[i] = mean (g1.perm) - mean (g2.perm)
}
p.permute <- (sum (abs (sampl.dist.p) >= abs(obs.diff.p)) + 1)/ (iterations+1)
순열 테스트의보고 된 p 값은 0.0053 입니다. OK, 올바르게 수행하면 순열과 파라 메트릭 ANOVA는 거의 동일한 결과를 제공합니다.
병줄
우선, 샘플 크기가 너무 작을 때 부트 스트랩이 도움이되지 않는다는 것을 알고 있습니다. 이 포스트는 더 나쁘고 오해의 소지가 있음을 보여 주었다 . 또한 두 번째 는 가설 검정이 주요 목표 일 때 순열 검정이 일반적으로 부트 스트랩보다 낫다는 점을 강조했습니다 . 그럼에도 불구하고이 글 은 컴퓨터 집약적 인 방법들 사이의 중요한 차이점을 다룹니다. 그러나 여기서 나는 다른 질문을 제기하고 싶습니다 (믿습니다).
가장 일반적인 부트 스트랩 접근 방식을 먼저 소개하겠습니다 (Bootstrap1 : 풀링 된 샘플 내에서 리샘플링 ).
s.size.g1 <- length (g1.lengths)
s.size.g2 <- length (g2.lengths)
pool <- lengths$lengths
obs.diff.b1 <- mean (g1.lengths) - mean (g2.lengths)
iterations <- 10000
sampl.dist.b1 <- NULL
set.seed (5)
for (i in 1 : iterations) {
resample <- sample (c(1:length (pool)), length(pool), replace = TRUE)
# "replace = TRUE" is the only difference between bootstrap and permutations
g1.perm = pool[resample][1 : s.size.g1]
g2.perm = pool[resample][(s.size.g1+1) : length(pool)]
sampl.dist.b1[i] = mean (g1.perm) - mean (g2.perm)
}
p.boot1 <- (sum (abs (sampl.dist.b1) >= obs.diff.b1) + 1)/ (iterations+1)
이러한 방식으로 수행 된 부트 스트랩의 P 값은 0.005 이다. 이것이 파라 메트릭 ANOVA 및 순열 테스트와 합리적이고 거의 동일하게 들리더라도, 우리가 후속 샘플을 추출한 샘플 을 풀링 했음을 기반으로이 부트 스트랩에서 H0를 정당화하는 것이 적절 합니까?
여러 과학 논문에서 찾은 다른 접근법. 특히, 연구원들은 부트 스트랩 이전에 HO를 충족시키기 위해 데이터를 수정하는 것을 보았습니다. CV 에서 @ jan.s 가 두 가지 수단을 비교하는 것이 목적인 게시물 질문에서 부트 스트랩의 특이한 결과를 설명 하는 매우 흥미로운 게시물을 발견했습니다 . 그러나 해당 게시물에서는 부트 스트랩 이전에 데이터가 수정 될 때 부트 스트랩을 수행하는 방법을 다루지 않습니다. 부트 스트랩 이전에 데이터가 수정되는 방식은 다음과 같습니다.
- H0는 두 그룹의 평균이 동일하다는 것을 나타냅니다.
- 풀링 된 표본의 평균에서 개별 관측 값을 빼면 H0이 적용됩니다.
이 경우, 데이터의 수정은 그룹 평균에 영향을 주어야하며, 그 차이는 있지만 그룹 내 (및 그룹 간)의 변동에는 영향을 미치지 않습니다.
- 수정 된 데이터는 추가 부트 스트랩의 기초가되며 샘플링은 각 그룹 내에서 별도로 수행된다는 경고가 있습니다.
- g1과 g2의 부트 스트랩 평균 간의 차이가 계산되고 그룹 간의 관찰 된 (수정되지 않은) 차이와 비교됩니다.
- 관찰 된 값을 반복 횟수로 나눈 값보다 크거나 같은 극단적 인 값의 비율은 p 값을 제공합니다.
다음은 코드입니다 (Bootstrap2 : 수정 후 그룹 내에서 리샘플링 ( H0이 TRUE 임)).
s.size.g1 <- length (g1.lengths)
s.size.g2 <- length (g2.lengths)
pool <- lengths$lengths
obs.diff.b2 <- mean (g1.lengths) - mean (g2.lengths)
# make H0 to be true (no difference between means of two groups)
H0 <- pool - mean (pool)
# g1 from H0
g1.H0 <- H0[1:s.size.g1]
# g2 from H0
g2.H0 <- H0[(s.size.g1+1):length(pool)]
iterations <- 10000
sampl.dist.b2 <- NULL
set.seed (5)
for (i in 1 : iterations) {
# Sample with replacement in g1
g1.boot = sample (g1.H0, replace = T)
# Sample with replacement in g2
g2.boot = sample (g2.H0, replace = T)
# bootstrapped difference
sampl.dist.b2[i] <- mean (g1.boot) - mean (g2.boot)
}
p.boot2 <- (sum (abs (sampl.dist.b2) >= obs.diff.b2) + 1)/ (iterations+1)
이러한 수행 된 부트 스트랩은 p의 0.514 값을 제공 하며 이는 이전 테스트와 크게 다릅니다. 나는 이것이 @ jan.s의 설명 을 다루어야한다고 생각 하지만, 열쇠가 어디에 있는지 알 수 없다 ...
H0 <- pool - mean (pool)
. 로 교체해야합니다 H0 <- c(g1.lengths - mean(g1.lengths), g2.lengths - mean(g2.lengths))
. 그러면 p- 값이 0.0023이됩니다. (이것은 Zenit이 그의 답변에서 설명한 것과 동일합니다.) 이것은 코드의 간단한 버그 일뿐입니다. @MichaelChernick의 CC