tl; dr: Começando com um conjunto de dados gerado sob o valor nulo, fiz uma nova amostragem de casos com substituição e conduzi um teste de hipótese em cada conjunto de dados reamostrado. Esses testes de hipótese rejeitam o nulo mais de 5% do tempo.
Na simulação abaixo, muito simples, eu conjuntos de dados com e um modelo OLS simples para cada um. Em seguida, para cada conjunto de dados, eu gero 1000 novos conjuntos de dados re-amostrando linhas do conjunto de dados original com substituição (um algoritmo especificamente descrito no texto clássico de Davison & Hinkley como apropriado para a regressão linear). Para cada um deles, eu me encaixo no mesmo modelo OLS. Por fim, cerca de 16% dos testes de hipótese nas amostras de bootstrap rejeitam o nulo , enquanto que devemos obter 5% (como fazemos nos conjuntos de dados originais).
Eu suspeitava que isso tivesse algo a ver com observações repetidas, causando associações infladas; portanto, para comparação, tentei duas outras abordagens no código abaixo (comentado). No método 2, eu corrijo e substituo por resíduos reamostrados do modelo OLS no conjunto de dados original. No método 3, eu desenho uma subamostra aleatória sem substituição. Ambas as alternativas funcionam, ou seja, seus testes de hipótese rejeitam o nulo 5% das vezes.
Minha pergunta: Estou certo de que observações repetidas são as culpadas? Se sim, considerando que essa é uma abordagem padrão para o bootstrap, onde exatamente estamos violando a teoria padrão do bootstrap?
Atualização # 1: Mais simulações
Eu tentei um cenário ainda mais simples, um modelo de regressão somente interceptar para . O mesmo problema ocorre.
# note: simulation takes 5-10 min on my laptop; can reduce boot.reps
# and n.sims.run if wanted
# set the number of cores: can change this to match your machine
library(doParallel)
registerDoParallel(cores=8)
boot.reps = 1000
n.sims.run = 1000
for ( j in 1:n.sims.run ) {
# make initial dataset from which to bootstrap
# generate under null
d = data.frame( X1 = rnorm( n = 1000 ), Y1 = rnorm( n = 1000 ) )
# fit OLS to original data
mod.orig = lm( Y1 ~ X1, data = d )
bhat = coef( mod.orig )[["X1"]]
se = coef(summary(mod.orig))["X1",2]
rej = coef(summary(mod.orig))["X1",4] < 0.05
# run all bootstrap iterates
parallel.time = system.time( {
r = foreach( icount( boot.reps ), .combine=rbind ) %dopar% {
# Algorithm 6.2: Resample entire cases - FAILS
# residuals of this model are repeated, so not normal?
ids = sample( 1:nrow(d), replace=TRUE )
b = d[ ids, ]
# # Method 2: Resample just the residuals themselves - WORKS
# b = data.frame( X1 = d$X1, Y1 = sample(mod.orig$residuals, replace = TRUE) )
# # Method 3: Subsampling without replacement - WORKS
# ids = sample( 1:nrow(d), size = 500, replace=FALSE )
# b = d[ ids, ]
# save stats from bootstrap sample
mod = lm( Y1 ~ X1, data = b )
data.frame( bhat = coef( mod )[["X1"]],
se = coef(summary(mod))["X1",2],
rej = coef(summary(mod))["X1",4] < 0.05 )
}
} )[3]
###### Results for This Simulation Rep #####
r = data.frame(r)
names(r) = c( "bhat.bt", "se.bt", "rej.bt" )
# return results of each bootstrap iterate
new.rows = data.frame( bt.iterate = 1:boot.reps,
bhat.bt = r$bhat.bt,
se.bt = r$se.bt,
rej.bt = r$rej.bt )
# along with results from original sample
new.rows$bhat = bhat
new.rows$se = se
new.rows$rej = rej
# add row to output file
if ( j == 1 ) res = new.rows
else res = rbind( res, new.rows )
# res should have boot.reps rows per "j" in the for-loop
# simulation rep counter
d$sim.rep = j
} # end loop over j simulation reps
##### Analyze results #####
# dataset with only one row per simulation
s = res[ res$bt.iterate == 1, ]
# prob of rejecting within each resample
# should be 0.05
mean(res$rej.bt); mean(s$rej)
Atualização # 2: A resposta
Várias possibilidades foram propostas nos comentários e respostas, e eu fiz mais simulações para testá-las empiricamente. Acontece que o JWalker está certo de que o problema é que precisamos centralizar as estatísticas de autoinicialização pela estimativa dos dados originais para obter a distribuição de amostragem correta em . No entanto, também acho que o comentário do whuber sobre a violação dos pressupostos dos testes paramétricos também está correto, embora neste caso realmente recebamos falsos positivos nominais quando solucionamos o problema do JWalker.
ids
ids <- unique(ids)