Предположим, у меня есть данные с двумя независимыми группами:
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 . Традиционный ANOVA предполагает, что группы имеют разные средние значения, когда критическое значение установлено на 0,05 (значение р равно 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 . Хорошо, если я сделал это правильно, перестановки и параметрический 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 в этой начальной загрузке на основе того, что мы только что объединили выборки, из которых мы взяли последующие выборки?
Другой подход я нашел в нескольких научных работах. В частности, я увидел, что исследователи модифицируют данные, чтобы соответствовать H0 до начальной загрузки. Осматривая, я нашел очень интересную запись в 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)
Такой выполненный начальный загрузчик даст значение р 0,514, которое сильно отличается от предыдущих тестов. Я считаю, что это связано с объяснением @ jan.s , но я не могу понять, где ключ ...
H0 <- pool - mean (pool)
. Это должно быть заменено на H0 <- c(g1.lengths - mean(g1.lengths), g2.lengths - mean(g2.lengths))
. Тогда вы получите р-значение 0,0023. (Это то же самое, что Зенит объяснил в своем ответе.) Это все, что нужно сделать, просто простая ошибка в коде. CC @MichaelChernick