Verwenden von Bootstrap unter H0, um einen Test auf die Differenz zweier Mittel durchzuführen: Ersetzen innerhalb der Gruppen oder innerhalb der gepoolten Probe


18

Angenommen, ich habe Daten mit zwei unabhängigen Gruppen:

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)

Es ist offensichtlich, dass die Stichprobengröße pro Gruppe verzerrt ist, wenn g1 6 Beobachtungen und g2 22 hat . Die traditionelle ANOVA schlägt vor, dass Gruppen unterschiedliche Mittel haben, wenn der kritische Wert auf 0,05 eingestellt ist (p-Wert ist 0,0044 ).

summary (aov (lengths~group, data = lengths))  

Da es mein Ziel ist, die mittlere Differenz zu vergleichen, können solche unausgeglichenen Daten und Daten mit kleinen Stichproben zu unangemessenen Ergebnissen mit dem herkömmlichen Ansatz führen. Daher möchte ich Permutationstest und Bootstrap durchführen.

PERMUTATIONSTEST

Die Nullhypothese (H0) besagt, dass die Mittelwerte der Gruppe gleich sind. Diese Annahme im Permutationstest ist gerechtfertigt, indem Gruppen in einer Stichprobe zusammengefasst werden. Dies stellt sicher, dass die Proben für zwei Gruppen aus der identischen Verteilung entnommen wurden. Durch wiederholtes Abtasten (oder genauer - Ummischen) der gepoolten Daten werden die Beobachtungen auf neue Weise den Proben neu zugeordnet (umgemischt), und die Teststatistik wird berechnet. Wenn Sie dies n-mal durchführen, erhalten Sie eine Stichprobenverteilung der Teststatistik unter der Annahme, dass H0 WAHR ist. Am Ende ist der p-Wert unter H0 die Wahrscheinlichkeit, dass die Teststatistik dem beobachteten Wert entspricht oder diesen überschreitet.

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)

Der gemeldete p-Wert des Permutationstests beträgt 0,0053 . OK, wenn ich es richtig gemacht habe, ergeben Permutationen und parametrische ANOVA nahezu identische Ergebnisse.

BOOTSTRAP

Zunächst ist mir bewusst, dass Bootstrap nicht helfen kann, wenn die Stichprobengröße zu klein ist. Dieser Beitrag hat gezeigt, dass es noch schlimmer und irreführend sein kann . Zweitens wurde hervorgehoben, dass der Permutationstest im Allgemeinen besser ist als der Bootstrap, wenn der Hypothesentest das Hauptziel ist. Dennoch werden in diesem großartigen Beitrag wichtige Unterschiede zwischen computerintensiven Methoden angesprochen. Ich möchte hier jedoch eine andere Frage stellen (glaube ich).

Lassen Sie mich zuerst den gebräuchlichsten Bootstrap-Ansatz vorstellen (Bootstrap1: Resampling innerhalb des gepoolten Beispiels ):

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)

Der P-Wert des so durchgeführten Bootstraps beträgt 0,005 . Auch wenn dies vernünftig und fast identisch mit der parametrischen ANOVA und dem Permutationstest klingt, ist es angemessen, H0 in diesem Bootstrap auf der Grundlage zu rechtfertigen, dass wir gerade Samples gepoolt haben, aus denen wir nachfolgende Samples gezogen haben?

Unterschiedlicher Ansatz fand ich in mehreren wissenschaftlichen Arbeiten. Insbesondere habe ich gesehen, dass Forscher die Daten modifizieren, um H0 vor dem Bootstrap zu erfüllen. Beim Durchsuchen habe ich einen sehr interessanten Beitrag im Lebenslauf gefunden, in dem @ jan.s ungewöhnliche Ergebnisse von Bootstrap in der Frage nach dem Beitrag erklärte, in der es darum ging, zwei Mittel zu vergleichen. In diesem Beitrag wird jedoch nicht behandelt, wie ein Bootstrap durchgeführt wird, wenn Daten vor dem Bootstrap geändert werden. Der Ansatz, bei dem die Daten vor dem Bootstrap geändert werden, sieht folgendermaßen aus:

  1. H0 besagt, dass die Mittelwerte zweier Gruppen gleich sind
  2. H0 gilt, wenn wir einzelne Beobachtungen vom Mittelwert der gepoolten Stichprobe abziehen

In diesem Fall sollte sich die Änderung der Daten auf die Mittelwerte der Gruppen und damit auf deren Unterschiede auswirken, jedoch nicht auf Abweichungen innerhalb (und zwischen) Gruppen.

  1. Geänderte Daten bilden die Grundlage für einen weiteren Bootstrap. Dabei ist zu beachten, dass die Probenahme in jeder Gruppe separat erfolgt .
  2. Die Differenz zwischen dem Bootstrap-Mittelwert von g1 und g2 wird berechnet und mit der beobachteten (nicht modifizierten) Differenz zwischen Gruppen verglichen.
  3. Der Anteil gleicher oder höherer Extremwerte als der beobachtete, dividiert durch die Anzahl der Iterationen, ergibt den p-Wert.

Hier ist der Code (Bootstrap2: Resampling innerhalb der Gruppen nach Änderung, dass H0 TRUE ist ):

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)

Solch ein durchgeführter Bootstrap ergibt einen p-Wert von 0,514, der sich im Vergleich zu früheren Tests erheblich unterscheidet. Ich glaube, dass dies mit der Erklärung von @ jan.s zu tun hat , aber ich kann nicht herausfinden, wo der Schlüssel ist ...


1
Interessantes Problem und schön präsentiert. Der Bootstrap hat Probleme, wenn die Stichprobengröße nur sehr klein ist, weil die ursprüngliche Stichprobe die Grundgesamtheit mit größerer Wahrscheinlichkeit nicht sehr gut darstellt. Die Stichprobengröße muss nicht sehr groß sein, damit der Bootstrap funktioniert. Ihre Stichprobengröße von 6 und 22 ist möglicherweise nicht so schlecht. In einer Arbeit von Efron (1983) wurde der Bootstrap mit einer Form von CV verglichen, um Fehlerraten für lineare Diskriminanzfunktionen bei Klassifizierungsproblemen mit 2 Klassen zu schätzen, wobei jede Trainingsstichprobengröße kleiner als 10 ist. Ich beschreibe dies in meinem Buch Bootstrap Methods ( 2007).
Michael R. Chernick

2
Mein Buch enthält auch ein Kapitel darüber, wann der Bootstrap fehlschlägt, und eine Diskussion über das Problem der kleinen Stichprobengröße.
Michael R. Chernick

Die einzige Linie , dass Sie in der Bootstrap # 2 Ansatz repariert werden muss , damit es funktioniert , lautet: H0 <- pool - mean (pool). Es muss ersetzt werden durch H0 <- c(g1.lengths - mean(g1.lengths), g2.lengths - mean(g2.lengths)). Dann erhalten Sie einen p-Wert von 0,0023. (Dies ist das Gleiche, was Zenit in seiner Antwort erklärt hat.) Das ist alles, was dazu gehört, nur ein einfacher Fehler im Code. CC zu @MichaelChernick
Amöbe sagt Reinstate Monica

Könnten diese Methoden überwältigt werden? Ich meine, ob sie einen Unterschied als signifikant erkennen können, wenn die Gruppen sehr groß sind: Pool> 43k.
Alex Alvarez Pérez

Antworten:


17

Hier ist meine Meinung dazu, basierend auf Kapitel 16 von Efrons und Tibshiranis Einführung in den Bootstrap (Seite 220-224). Das kurze daran ist, dass Ihr zweiter Bootstrap-Algorithmus falsch implementiert wurde, aber die allgemeine Idee ist richtig.

Bei der Durchführung von Bootstrap-Tests muss sichergestellt werden, dass die Neuabtastungsmethode Daten generiert, die der Nullhypothese entsprechen. Ich werde die Schlafdaten in R verwenden, um diesen Beitrag zu veranschaulichen. Beachten Sie, dass ich die studentisierte Teststatistik anstelle der im Lehrbuch empfohlenen Mittelwertdifferenz verwende.

Der klassische t-Test, der anhand eines Analyseergebnisses Informationen über die Stichprobenverteilung der t-Statistik erhält, liefert folgendes Ergebnis:

x <- sleep$extra[sleep$group==1] y <- sleep$extra[sleep$group==2]
t.test(x,y)
t = -1.8608, df = 17.776, p-value = 0.07939

n1n2

# pooled sample, assumes equal variance
pooled <- c(x,y)
for (i in 1:10000){
  sample.index <- sample(c(1:length(pooled)),replace=TRUE)
  sample.x <- pooled[sample.index][1:length(x)]
  sample.y <- pooled[sample.index][-c(1:length(y))]
  boot.t[i] <- t.test(sample.x,sample.y)$statistic
}
p.pooled <-  (1 + sum(abs(boot.t) > abs(t.test(x,y)$statistic))) / (10000+1) 
p.pooled
[1] 0.07929207

H0H0H0z¯

x~i=xix¯+z¯
y~i=yiy¯+z¯

x~/y~z¯H0

# sample from H0 separately, no assumption about equal variance
xt <- x - mean(x) + mean(sleep$extra) #
yt <- y - mean(y) + mean(sleep$extra)

boot.t <- c(1:10000)
for (i in 1:10000){
  sample.x <- sample(xt,replace=TRUE)
  sample.y <- sample(yt,replace=TRUE)
  boot.t[i] <- t.test(sample.x,sample.y)$statistic
}
p.h0 <-  (1 + sum(abs(boot.t) > abs(t.test(x,y)$statistic))) / (10000+1)  # 
p.h0
[1] 0.08049195

Dieses Mal haben wir ähnliche p-Werte für die drei Ansätze erhalten. Hoffe das hilft!


1
Würdest du freundlich sein und erklären, warum dem Folgenden '1' hinzugefügt wurde? (1 + sum(abs(boot.t) > abs(t.test(x,y)$statistic))) / (10000+1)Stattdessen: mean(abs(boot.t) > abs(t.test(x,y)$statistic))Danke für deine Zeit.
TG_Montana

+1. Hat dieser Bootstrap-On-Modified-Data-To-Sample-From-H0-Ansatz einen bestimmten Namen?
Amöbe sagt Reinstate Monica

3
H0p-veinlue=Anzahl {t>tObs}BB

@amoeba: Ich bin mir nicht sicher, ob dieses Verfahren einen formalen oder vereinbarten Namen hat, aber ich denke, es kann eher als Bootstrap-Test für die Mittelgleichheit als für Verteilungen beschrieben werden . Die Seite mit der vollständigen Vorgehensweise fehlt in Google Books , die Motivation finden Sie jedoch auf Seite 223. Eine weitere Beschreibung finden Sie in diesen Hinweisen auf Seite 13 ( galton.uchicago.edu/~eichler/stat24600/Handouts/bootstrap). pdf ).
Zenit

(+1) Ausgezeichnete Antwort. Können Sie erläutern, warum "dieser Algorithmus [die Daten selbst ohne Zentrierung erneut abtastet] tatsächlich prüft, ob die Verteilung von x und y identisch ist"? Ich verstehe, dass diese Resampling-Strategie sicherstellt, dass die Distributionen gleich sind, aber warum testet sie , dass sie gleich sind?
Half-Pass
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.