Kernfragen dieser Lehreinheit
- Wie können Variablen und ganze Modelle simuliert werden?
- Wie lassen sich der
-Fehler (Type I-Error, Fehler erster Art) und die Power (Testmacht, Teststärke) empirisch bestimmen? - Welche anderen Möglichkeiten, den
-Fehler und die Power zu bestimmen, gibt es? - Wie lassen sich Power-Plots erstellen und was bedeuten sie?
Einleitung
Nachdem wir uns jetzt viel mit der Durchführung der inferenzstatistischen Testung befasst haben, wollen wir den Fokus auf eine etwas übergeordnete Ebene legen. Dieses Tutorial befasst sich damit, vor einer Testung eine Stichprobe festzulegen oder diese nach der Testung zu beurteilen. Wir brauchen den Datensatz für dieses Tutorial nicht, weshalb wir ihn auch nicht einladen.
Rückblick Tests
In den vergangenen Sitzungen haben wir verschiedene Tests für unterschiedliche Fragestellungen kennengelernt: z.B. den
Dazu können wir ein
Äquivalent dazu können wir das Quantil der Verteilung bestimmen, ab dem Werte eine Wahrscheinlichkeit kleiner als
Beide Ansätze kommen zum identischen Ergebnis, weil Quantil und p*
und q*
für verschiedene Verteilungen diese Übersetzung vornehmen.
Gilt die Null-Hypothese, so sollte der Test in nur höchstens
Wenn wir das gleiche Experiment unendlich häufig und unabhängig voneinander wiederholen könnten und dabei unendlich häufig aus einer Population ziehen würden, in welcher es keinen Effekt gibt, dann sollte in höchstens
der Wiederholungen (auch Replikationen genannt) rein durch Zufall ein signifikantes Ergebnis beim Durchführen des inferenzstatistischen Test herauskommen.
Andersherum sollte ein inferenzstatistischer Test die
Zurück zu unserem Gedankenexperiment:
Eine Power von
bedeutet, wenn wir das gleiche Experiment unendlich häufig und unabhängig voneinander wiederholen könnten und dabei unendlich häufig aus einer Population ziehen würden, in welcher es einen Effekt gibt, dann sollte in mindestens der Fälle ein signifikantes Ergebnis beim Durchführen des inferenzstatistischen Test herauskommen, um von hinreichender Power zu sprechen.
Im Folgenden wollen wir dieses Gedankenexperiment in die Tat umsetzen und unsere Kenntnisse über das Simulieren von Zufallszahlen verwenden, um die Power und den Fehler 1. Art (t.test()
). Als Zusatz gibt es für die Korrelation als ein Zusammenhangsmaß auch ein Beispiel zum Korrelationstest in Appendix A (mit der Funktion cor.test()
, welche erst in späteren Sitzungen genauer vorgestellt wird). Da wir nun also Daten simulieren brauchen wir in diesem Tutorial den Datensatz nicht.
Simulation und -Fehler
Sie haben nun die Möglichkeit, in einen möglichen Forschungsbereich von Methodiker:innen hineinzublicken: Simulationsstudien. Um das beschriebene Gedankenexperiment umzusetzen, müssen wir sehr häufig Stichproben aus der Population ziehen und unseren Test (z.B. einen Mittelwertsvergleich) durchführen. Die Realität hat dabei zwei grundlegende Probleme:
- Wir wissen nicht, ob in der Realität die
oder gilt. - Um zuverlässige Wahrscheinlichkeitsaussagen zu machen müssen wir die Untersuchung sehr häufig wiederholen, was in den allermeisten tatsächlich empirischen Fällen nicht praktikabel ist.
Daher behelfen wir uns in methodologischer Forschung mit Simulationsstudien.
Mittelwertsvergleiche: -Test unter
Der (klassische)
- die Erhebungen sind voneinander unabhängig
- die Varianzen in den beiden Gruppen sind gleich groß
- die Variable ist in den Populationen normalverteilt
Wir simulieren nun eine Variable rnorm()
kennengelernt. Wie im Beitrag zu Verteilungen besprochen, können wir mit set.seed()
die Analysen replizierbar machen. Das bedeutet, dass eure Werte mit den hier stehenden Werten übereinstimmen sollten.
N <- 20
set.seed(1234)
X_1 <- rnorm(N)
X_2 <- rnorm(N)
Die Werte der ersten Gruppe legen wir in dem Objekt X_1
ab, die Werte der zweiten Gruppe im Objekt X_2
. Dadurch dass wir die Werte für beide Gruppen getrennt simuliert haben, sind die Werte voneinander unabhängig (erste Voraussetzung erfüllt). Dadurch, dass wir mit rnorm()
arbeiten, machen wir außerdem explizit, dass wir Werte erzeugen, die (in der Population) der Normalverteilung folgen (dritte Voraussetzung erfüllt). Dadurch, dass wir in rnorm()
außerdem für beide Variablen die Voreinstellung sd = 1
für die Standardabweichung nutzen, ist auch die zweite Voraussetzung (Homoskedastizität) erfüllt.
Zusätzlich haben wir in beiden Fällen auch die Voreinstellung mean = 0
für den Mittelwert benutzt. Dadurch gilt
mean(X_1)
## [1] -0.2506641
mean(X_2)
## [1] -0.5770699
Sie weichen (zufällig) von der 0 ab. Diese Abweichung wird auch Samplevariation (Stichprobenschwankung) genannt.
Die Frage, die wir uns in der Inferenzstatistik nun stellen ist, ob der Unterschied, den wir in der Stichprobe beobachten, sich auf die angenommene Grundgesamtheit verallgemeinern lässt.
Wir können nun mithilfe des var.equal = TRUE
wählen, da sonst die Variante mit Welch-Korrektur gerechnet wird):
ttestH0 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH0
##
## Two Sample t-test
##
## data: X_1 and X_2
## t = 1.1349, df = 38, p-value = 0.2635
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -0.2558241 0.9086358
## sample estimates:
## mean of x mean of y
## -0.2506641 -0.5770699
ttestH0$statistic # t-Wert
## t
## 1.134902
ttestH0$p.value # zugehöriger p-Wert
## [1] 0.2635244
Die Mittelwertsdifferenz liegt bei 0.3264, was einen
Wir sind an dieser Stelle aber nicht daran interessiert, wie der
Deshalb wollen wir hier bspw. die replicate()
-Funktion verwenden. Mit dieser Funktion wird irgendein Stück R-Code (eine “Expression”, daher der Namen des Arguments: expr
) n
-mal wiederholt. Wenn wir z.B. 5 mal drei Werte aus einer Normalverteilung ziehen wollen, kann das Ganze so aussehen:
replicate(n = 5, expr = rnorm(3))
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1.4494963 -0.2806230 -1.1073182 -0.4968500 -1.1088896
## [2,] -1.0686427 -0.9943401 -1.2519859 -1.8060313 -1.0149620
## [3,] -0.8553646 -0.9685143 -0.5238281 -0.5820759 -0.1623095
replicate()
kann aber nicht nur einzelne Funktionen, sondern auch mehrere Zeilen R-Code entgegennehmen, solange diese in geschwungenen Klammern { ... }
angegeben werden. Wenn wir zwei unabhängige Variablen erstellen, mit einem
X_1 <- rnorm(N)
X_2 <- rnorm(N)
ttestH0 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH0$p.value
N
hatten wir oben bereits als 20 festgelegt. Mit replicate()
können wir den Code beliebig häufig durchführen. Z.B. zunächst 10 mal:
set.seed(1234)
replicate(n = 10, expr = {X_1 <- rnorm(N)
X_2 <- rnorm(N)
ttestH0 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH0$p.value})
## [1] 0.26352442 0.03081077 0.21285027 0.27429670 0.53201656 0.79232864 0.93976306 0.43862992 0.96766599 0.68865560
Uns werden insgesamt 10 pt_H0
ab (für
set.seed(1234)
pt_H0 <- replicate(n = 10000, expr = {X_1 <- rnorm(N)
X_2 <- rnorm(N)
ttestH0 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH0$p.value})
Schauen wir uns doch mal die Verteilung der
hist(pt_H0, breaks = 20)

Die
mean(pt_H0 < 0.05)
## [1] 0.0484
Somit wird die Nullhypothese hier in 4.84% der Fälle verworfen. Dies zeigt uns, dass der
Im Übrigen hätten wir auch die ganze Prozedur mithilfe der empirischen statistic
im Test-Objekt angelegt):
set.seed(1234)
tt_H0 <- replicate(n = 10000, expr = {X_1 <- rnorm(N)
X_2 <- rnorm(N)
ttestH0 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH0$statistic})
Wir können uns die Verteilung dieser Werte ansehen, um zu prüfen, ob die Werte annähernd dt(x = x, df = 38)
, wobei x
die gewünschte x-Koordinate ist:
hist(tt_H0, breaks = 50, freq = FALSE) # freq = FALSE, damit relative Häufigkeiten eingetragen werden!
x <- seq(-4, 4, 0.01) # Sequenz von -4 bis 4 in 0.01 Schritten
lines(x = x, y = dt(x = x, df = 38), lwd = 2) # lwd = Liniendicke

Die empirischen abs()
) der empirischen
t_krit <- qt(p = .975, df = 38)
mean(abs(tt_H0) > t_krit) # empirischer Alpha-Fehler
## [1] 0.0484
Die Analyse kommt zum exakt gleichen Ergebnis. Das liegt daran, dass - wie oben bereits festgehalten - der dt()
) passt sehr gut zum Histogramm!
Poweranalysen
Mit einer Power-Analyse untersuchen wir im Grunde, wie sich die Wahrscheinlichkeit die Nullhypothese zu verwerfen, verändert, je nachdem wie groß der Effekt oder die Stichprobe ist. Dem wollen wir nun nachgehen und entsprechend unsere Daten unter der Alternativhypothese simulieren.
Mittelwertsvergleiche: -Test unter
In der Inferenzstatistik gibt es im Grunde nicht “die” Alternativhypothese, sondern eine ganze Batterie an Alternativhypothesen. Beim ungerichteten Mittelwertsvergleich sieht die Alternativhypothese so aus:
was natürlich äquivalent zur folgenden Aussage zur Differenz der beiden Mittelwerte ist:
Hier wird X_1
und X_2
um 0.5 im Mittelwert, da X_1
einen Mittelwert von 0 hat und X_2
einen Mittelwert von 0 + 0.5 = 0.5.”
set.seed(12345)
X_1 <- rnorm(N)
X_2 <- rnorm(N) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$p.value
## [1] 0.0160865
Der empirische
set.seed(12345)
pt_H1 <- replicate(n = 10000, expr = {X_1 <- rnorm(N)
X_2 <- rnorm(N) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$p.value})
mean(pt_H1 < 0.05) # empirische Power
## [1] 0.335
hist(pt_H1, breaks = 20)

Die empirische Power (die Wahrscheinlichkeit in unserer Simulation, dass die
Woran liegt nun dieses schiefe Histogramm? Wir schauen uns dazu noch schnell die
set.seed(12345)
tt_H1 <- replicate(n = 10000, expr = {X_1 <- rnorm(N)
X_2 <- rnorm(N) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$statistic})
hist(tt_H1, breaks = 50, freq = FALSE) # freq = FALSE, damit relative Häufigkeiten eingetragen werden!
x <- seq(-4, 4, 0.01) # Sequenz von -4 bis 4 in 0.01 Schritten
lines(x = x, y = dt(x = x, df = 38), lwd = 2) # lwd = Liniendicke

Der Grafik entnehmen wir, dass die gesamte Verteilung der empirischen t-Werte verschoben ist im Vergleich zur theoretischen Verteilung (Linie). Somit ist klar, dass die Hypothese häufiger verworfen werden muss, da die kritischen
Nun zurück zur geschätzten Power: Eine Power von 0.335 ist allerdings nicht besonders hoch. Nur in etwas mehr als einem Drittel der Replikationen wurde die Mittelwertsdifferenz als statistisch bedeutsam betitelt. Wir wissen aber, weil wir das Modell vorgegeben haben, dass die
Mit größerer Stichprobe wird die Power steigen (was wir im Abschnitt Power-Plots noch deutlicher sehen werden).
Power-Plots
Mit einem einzelnen Power-Wert lässt sich in der Regel nicht so viel anfangen. Aus diesem Grund werden Power-Plots erstellt, welche darstellen, wie sich die Power bspw. über unterschiedliche Stichprobengrößen (um die Asymptotik des Tests zu prüfen) oder über unterschiedliche Effektgrößen verändert.
Power-Plots für Mittelwertsunterschiede
Wir schauen uns die Power-Plots diesmal nur für die Mittelwertsunterschiede an. Zunächst beginnen wir mit der Asymptotik. Wir wiederholen im einfachsten Fall das Experiment von oben für 5 Stichprobengrößen:
set.seed(12345)
pt_H1_20 <- pt_H1
pt_H1_40 <- replicate(n = 10000, expr = {X_1 <- rnorm(40)
X_2 <- rnorm(40) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$p.value})
pt_H1_60 <- replicate(n = 10000, expr = {X_1 <- rnorm(60)
X_2 <- rnorm(60) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$p.value})
pt_H1_80 <- replicate(n = 10000, expr = {X_1 <- rnorm(80)
X_2 <- rnorm(80) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$p.value})
pt_H1_100 <- replicate(n = 10000, expr = {X_1 <- rnorm(100)
X_2 <- rnorm(100) + 0.5
ttestH1 <- t.test(X_1, X_2, var.equal = TRUE)
ttestH1$p.value})
Nun haben wir eine ganze Menge an
t_power <- c(mean(pt_H1_20 < 0.05),
mean(pt_H1_40 < 0.05),
mean(pt_H1_60 < 0.05),
mean(pt_H1_80 < 0.05),
mean(pt_H1_100 < 0.05))
t_power
## [1] 0.3350 0.5991 0.7700 0.8809 0.9369
Wir sehen sehr gut, dass die Power ansteigt. Der zugehörige Power-Plot sieht nun so aus (zunächst legen wir die Stichproben in Ns
ab):
Ns <- seq(20, 100, 20)
plot(x = Ns, y = t_power, type = "b",
main = "Power vs. N", xlab = "n", ylab = "Power des t-Tests mit d = .5")

Dem Plot entnehmen wir, dass ab etwas über
Genauso könnten wir uns fragen, wie groß ein Effekt sein muss, damit mit der vorliegenden Stichprobengröße und mit hinreichend großer Wahrscheinlichkeit ein signifikantes Ergebnis gefunden wird. In diesem Fall sprechen wir von einer Sensitivitätsanalyse. Dies schauen Sie sich als Übung an!
Wenn man dies auf die Spitze treibt, dann landet man vielleicht bei diesem schönen Plot:

Auf der x-Achse ist die Mittelwertsdifferenz dargestellt,

Wir sehen, dass die Power stets mit der Stichprobengröße wächst (es sei denn, der Effekt ist exakt 0, dann haben wir eine horizontale Linie auf dem
Power analytisch bestimmen
Nun wollen wir die Power von Tests “analytisch” bestimmen, also durch formeln. Dazu nutzen wir das WebPower
-Paket. Dieses ist eines von vielen Paketen, mit welchen die Power unterschiedlicher statistischer Tests bestimmt werden können. Wir beginnen damit das Paket zu laden (nach dem es installiert wurde mit install.packages
):
library(WebPower)
Nun wollen wir die Power eines wp.t
. Das wp
kürzel steht hierbei einfach nur für WebPower
. Die Argumente der Funktion erhalten wir so:
args(wp.t)
## function (n1 = NULL, n2 = NULL, d = NULL, alpha = 0.05, power = NULL,
## type = c("two.sample", "one.sample", "paired", "two.sample.2n"),
## alternative = c("two.sided", "less", "greater"), tol = .Machine$double.eps^0.25)
## NULL
Mit help(wp.t)
erhalten wir zu jedem dieser Argumente auch noch weitere Informationen sowie Beispiele. n1
und n2
sind die Stichprobengrößen der 1. und 2. Gruppe. Wenn wir n2
frei lassen (oder = NULL
), dann wird angenommen, dass beide Stichproben gleich groß sind. d
ist die standardisierte Effektgröße
sie nimmt also an, dass die Variablen standardisiert sind. alpha
ist das zugehörige power
können wir einen Zielwert für die Power übergeben. type
gibt an, welche Art von "two.sample"
, "one.sample"
, "paired"
und "two.sample.2n"
. Dies steht für also 2 unabhängige Stichproben (gleiche Stichprobengröße, "two.sample"
), 1-Stichprobentest ("one.sample"
), gepaarter "paired"
) und "two.sample.2n"
). Bei
wp.t(n1 = 20, d = .5, type = "two.sample", alternative = "two.sided")
## Two-sample t-test
##
## n d alpha power
## 20 0.5 0.05 0.337939
##
## NOTE: n is number in *each* group
## URL: http://psychstat.org/ttest
Unsere simulierte Power von 0.335 liegt sehr nah an den theoretischen 0.337939 dran.
Sensitivitätsanalysen
Haben wir nun nur 20 Personen pro Gruppe untersucht, können wir uns fragen, wie groß denn der Effekt hätte sein müssen, damit wir eine Power von power = .8
eintragen und dafür d
leer lassen:
wp.t(n1 = 20, power = .8, type = "two.sample", alternative = "two.sided")
## Two-sample t-test
##
## n d alpha power
## 20 0.9091587 0.05 0.8
##
## NOTE: n is number in *each* group
## URL: http://psychstat.org/ttest
Wir bräuchten also eine Mittelwertsdifferenz von 0.9091587.
Poweranalysen und Präregistrierungen
Um eine Studie sinnvoll zu planen, können wir mit Hilfe des WebPower
-Pakets auch nach der nötigen Stichprobengröße fragen. Das funktioniert ähnlich wie bei der Sensitivitätsanalyse, indem wir n1
und n2
frei lassen und dafür power
und d
vorgeben:
wp.t(d = .5, power = .8, type = "two.sample", alternative = "two.sided")
## Two-sample t-test
##
## n d alpha power
## 63.76561 0.5 0.05 0.8
##
## NOTE: n is number in *each* group
## URL: http://psychstat.org/ttest
Für eine standardisierte Mittelwertsdifferenz von .5 brauchen wir also eine Stichprobengröße pro Gruppe von
Gerichtete Hypothesen mit WebPower
Eine wichtige Ergänzung sollte an dieser Stelle für gerichtete Hypothesen erwähnt werden: wenn Sie die Hypothese richten, müssen Sie gleichzeitig auf das Vorzeichen von d
achten. Wenn wir für unseren
wp.t(d = .5, power = .8, type = "two.sample", alternative = "greater")
## Two-sample t-test
##
## n d alpha power
## 50.1508 0.5 0.05 0.8
##
## NOTE: n is number in *each* group
## URL: http://psychstat.org/ttest
Wenn wir aber annehmen, dass der Effekt umgedreht ist, bei
wp.t(d = .5, power = .8, type = "two.sample", alternative = "less")
## Error in uniroot(function(n) eval(p.body) - power, c(2 + 1e-10, 1e+07), : keine Vorzeichenwechsel nach 1000 Iterationen gefunden
Die Funktion ist nicht in der Lage, das nötige alternative = "less"
) nicht zuverlässig aufgedeckt werden kann, wenn
Dazu hier ein Warnhinweis, bezüglich eines Bugs in WebPower: wenn Sie Sensitivitätsanalyse betreiben, funktioniert das derzeit nur für “größer als” Aussagen. Für die Gegenrichtung erhalten Sie immer eine Fehlermeldung:
wp.t(n1 = 20, n2 = 20, power = .8, type = "two.sample", alternative = "less")
## Error in uniroot(function(d) eval(p.body) - power, c(-10, 5), tol = tol, : keine Vorzeichenwechsel nach 1000 Iterationen gefunden
wp.t(n1 = 20, n2 = 20, power = .8, type = "two.sample", alternative = "greater")
## Two-sample t-test
##
## n d alpha power
## 20 0.8006879 0.05 0.8
##
## NOTE: n is number in *each* group
## URL: http://psychstat.org/ttest
Dies ist zwar in diesem Fall nicht von dramatischer Konsequenz, weil das gesamte Verfahren symmetrisch ist, aber wenn Sie z.B. ungleiche Stichproben haben (type = "two.sample.2n"
) sollten Sie diese explizit im Auge behalten.
Appendix A
Simulation von linearen Beziehungen
Lineare Beziehungen zwischen Variablen: Korrelationstest unter
Der (klassische) Korrelationstest hat fast die identischen Voraussetzungen wie der
- die Erhebungen sind voneinander unabhängig
- die Varianzen in den beiden Gruppen sind gleich groß
- die Variablen sind in der Population normalverteilt
- die Variablen hängen linear zusammen
Wie bei den vorherigen Berechnungen des t-Tests simulieren wirs uns wieder Daten. Die beiden Variablen, die wir gleich korrelieren wollen, nennen wir Y
und Z
.
set.seed(1234)
Y <- rnorm(N)
Z <- rnorm(N)
cor(Y, Z) # empirische Korrelation
## [1] -0.2765719
cortestH0 <- cor.test(Y, Z)
cortestH0$p.value # empirischer p-Wert
## [1] 0.2378304
Die empirische Korrelation liegt bei -0.28. Die wahre Korrelation liegt bei 0, da R Zufallsvektoren unabhängig voneinander simuliert. Der
set.seed(1234)
pcor_H0 <- replicate(n = 10000, expr = {Y <- rnorm(N)
Z <- rnorm(N)
cortestH0 <- cor.test(Y, Z)
cortestH0$p.value})
Die
hist(pcor_H0, breaks = 20)

Das empirische
mean(pcor_H0 < 0.05)
## [1] 0.0481
Somit wird die Nullhypothese hier in 4.81% der Fälle verworfen. Dies zeigt uns, dass auch der Korrelationstest unter
Die Power für den Korrelationstest zu bestimmen, ist für diese Sitzung als Übungsaufgabe geplant!
Auch für Korrelationen können wir mit WebPower
vorgehen. Die Funktion hierzu heißt wp.correlation
.