Suponha que eu tenha dados com dois grupos independentes:
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)
É evidente que o tamanho da amostra por grupo é enviesado, onde g1 tem 6 observações e g2 tem 22 . A ANOVA tradicional sugere que os grupos têm médias diferentes quando o valor crítico é definido como 0,05 (o valor de p é 0,0044 ).
summary (aov (lengths~group, data = lengths))
Dado que meu objetivo é comparar a diferença média, esses dados amostrados desequilibrados e pequenos podem gerar resultados inadequados com a abordagem tradicional. Portanto, quero executar o teste de permutação e a inicialização.
ENSAIO DE PERMUTAÇÃO
A hipótese nula (H0) afirma que as médias do grupo são as mesmas. Essa suposição no teste de permutação é justificada pelo agrupamento de grupos em uma amostra. Isso garante que as amostras para dois grupos foram retiradas da distribuição idêntica. Por amostragem repetida (ou mais precisamente - reorganização) dos dados agrupados, as observações são realocadas (embaralhadas) para as amostras de uma nova maneira, e a estatística de teste é calculada. Realizando isso n vezes, fornecerá distribuição de amostragem das estatísticas de teste sob a suposição de que H0 é TRUE. No final, sob H0, o valor de p é a probabilidade de que a estatística do teste seja igual ou superior ao valor observado.
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)
O valor p reportado do teste de permutação é 0,0053 . OK, se eu fiz corretamente, permutações e ANOVA paramétrica dão resultados quase idênticos.
BOOTSTRAP
Antes de tudo, sei que o bootstrap não pode ajudar quando o tamanho da amostra é muito pequeno. Este post mostrou que pode ser ainda pior e enganador . Além disso, o segundo destacou que o teste de permutação geralmente é melhor do que o bootstrap quando o teste de hipóteses é o objetivo principal. No entanto, este ótimo post aborda diferenças importantes entre os métodos intensivos em computador. No entanto, aqui quero levantar (acredito) uma questão diferente.
Deixe-me apresentar primeiro a abordagem de bootstrap mais comum (Bootstrap1: reamostragem na amostra em pool ):
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)
O valor p do bootstrap realizado dessa maneira é 0,005 . Mesmo que isso pareça razoável e quase idêntico ao teste paramétrico de ANOVA e permutação, é apropriado justificar H0 nesse bootstrap com base no fato de termos acabado de reunir amostras das quais extraímos amostras subsequentes?
Abordagem diferente que encontrei em vários trabalhos científicos. Especificamente, vi que os pesquisadores modificam os dados para atender ao H0 antes do bootstrap. Pesquisando, encontrei um post muito interessante no CV, onde @ jan.s explicou resultados incomuns do bootstrap na pergunta do post, onde o objetivo era comparar dois meios. No entanto, nesse post, não é abordado como executar a inicialização quando os dados são modificados antes da inicialização. A abordagem na qual os dados são modificados antes da inicialização é assim:
- H0 afirma que as médias de dois grupos são as mesmas
- H0 é verdadeiro se subtrairmos as observações individuais da média da amostra agrupada
Nesse caso, a modificação dos dados deve afetar a média dos grupos e, portanto, sua diferença, mas não a variação dentro (e entre) dos grupos.
- Os dados modificados servirão de base para mais bootstrap, com ressalvas de que a amostragem é realizada dentro de cada grupo separadamente .
- A diferença entre a média inicializada de g1 e g2 é calculada e comparada com a diferença observada (não modificada) entre os grupos.
- A proporção de valores iguais ou mais extremos do que o observado, dividido pelo número de iterações, fornecerá o valor p.
Aqui está o código (Bootstrap2: reamostragem nos grupos após a modificação que H0 é VERDADEIRO ):
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)
Esse bootstrap executado dará um valor de p de 0,514, que é tremendamente diferente em comparação com testes anteriores. Acredito que isso tenha a ver com a explicação do @ jan.s , mas não consigo descobrir onde está a chave ...
H0 <- pool - mean (pool)
. Ele precisa ser substituído por H0 <- c(g1.lengths - mean(g1.lengths), g2.lengths - mean(g2.lengths))
. Então você obterá o valor-p de 0,0023. (É a mesma coisa que o Zenit explicou em sua resposta.) Isso é tudo o que existe, apenas um simples bug no código. CC para @MichaelChernick