Nullhypothesen-Signifikanztest (NHST): Einführung t-Test

Übung Forschungsmethodik I | WS 2023/24

Autor
TU Chemnitz

C. Maiwald

Professur Forschungsmethoden und Analyseverfahren in der Biomechanik

1 Funktionsaufruf

Der t-Test wird in R mit der Funktion t.test() durchgeführt. Die Funktion ist für alle Varianten des t-Tests (Einstichproben-t-Test, t-Test für abhängige Stichproben, t-Test für unabhängige Stichproben) einsetzbar. Über Funktionsargumente wird gesteuert, welche Art des t-Tests durchgeführt wird.

2 Der Einstichproben-t-Test (t-Test für abh. Stichproben)

Wir nutzen dieselben Daten wie im Beispiel der Vorlesung und prüfen die Wirksamkeit des koordinativen Trainingsprogramms für die jungen Senioren aus MODALIS (Alter <= 60) anhand der Lacrosse-Scores zwischen den Messzeitpunkten pre und post. Einstichproben-t-Test und t-Test für abhängige Stichproben sind identisch, da bei zwei abhängigen Stichproben zunächst die intrasubjektive Differenz der Messwerte gebildet wird und somit aus zwei Stichproben eine Stichprobe aus Differenzwerten entsteht.

2.1 Datensatz bilden

Zunächst laden wir den Datensatz MODALIS und bilden die Subgruppe der bis zu 60-Jährigen Erwachsenen / Senioren, wählen zudem die Spalten mit pre und post Scores aus.

load("MODALIS.RData")

# Subdatensatz bilden
U60 <- subset(MODALIS, gruppe == "E" & alter <= 60, select=c(lacrosse_pre, lacrosse_post))

2.2 Prüfung der Voraussetzungen für einen t-Test

Vor jedem statistischen Test sollte man sich die Daten zunächst ansehen und auf die Einhaltung der Testvoraussetzungen prüfen. Im Fall des Einstichproben-t-Tests ist das die Normalverteilung der Stichprobe (d. h. im Beispiel die Normalverteilung der Differenzen aus pre und post).

Diese Eigenschaft prüft man recht simpel grafisch per Histogramm. Wir müssen uns die Differenzen zuvor jedoch händisch berechnen:

Lacrosse.postpre <- U60$lacrosse_post - U60$lacrosse_pre

hist(Lacrosse.postpre)

Wir erkennen eine einigermaßen symmetrische und – mit etwas Phantasie – annähernd normale Häufigkeitsverteilung. Eine objektivere Prüfung auf Normalverteilung gelingt alklerdings nur mit Hilfe eines statistischen Tests, in unserem Fall können wir den Shapiro-Wilk-Test einsetzen. Wird der Test statistisch signifikant, weichen unsere Differenzen von der Normalverteilungsannahme ab und die Testvoraussetzungen für den t-Test wären verletzt.

shapiro.test(Lacrosse.postpre)

    Shapiro-Wilk normality test

data:  Lacrosse.postpre
W = 0.9881, p-value = 0.7036

Wir erhalten ein nicht-signifikantes Ergebnis (p-Wert deutlich oberhalb der üblichen Signifikanzgrenze von 5%: \(p>\alpha\)) und können folglich den Einstichproben-t-Test durchführen.

2.3 t-Test durchführen

Den t-Test für eine Stichprobe kann man nun auf drei verschiedene Weisen durchführen:

  1. Wir bilden die intraindividuellen Differenzen zwischen den Messzeitpunkten selbst und rechnen den Test mit nur einer Variable bzw. einer Stichprobe der Differenzwerte. Hier muss kein data.frame verwendet werden, ein Vektor der Differenzen genügt.
  2. Wir geben beide Variablen im Funktionsaufruf an und teilen R mit, dass wir paarige Daten nutzen. R berechnet die Differenzen dann automatisch. Auch hier können zwei Vektoren mit den Testscores zum Einsatz kommen, ein data.frame ist nicht erforderlich.
  3. Wir schreiben den t-Test per Formelschreibweise (siehe VL-Skript). Dazu müssen wir die Daten allerdings vorher in ein langes Format bringen und sollten sie in ein data.frame einbetten.

2.3.1 Version 1: Differenzen von Hand berechnen

Hierbei kann man die Richtung der Differenzbildung einfach nachvollziehen, da man die Differenz selbst erzeugt. Die Differenzen haben wir für das Histogramm oben bereits berechnet und nutzen sie hier direkt für den t-Test:

pairedTT1 <- t.test(Lacrosse.postpre)
print(pairedTT1)

    One Sample t-test

data:  Lacrosse.postpre
t = 8.4397, df = 75, p-value = 1.736e-12
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 0.7287769 1.1791179
sample estimates:
mean of x 
0.9539474 
Interpretation

Diese Ausgabe ist recht übersichtlich und weitgehend selbsterklärend. Die wesentliche Ergebniszeile enthält den t-Wert (das ist der empirisch ermittelte t-Wert der Stichprobendaten, im VL-Skript als \(t_{emp}\) bezeichnet), die Angabe der Freiheitsgrade des Tests (hier: \(df=n-1 = 76\), da insgesamt 77 Probanden vorhanden sind) und den zum t-Wert ermittelten p-Wert (in wiss. Notation: der Teil e-12 des p-Werts übersetzt sich in einen Exponent, also \(1.736\times 10^{-12}\)). Dieser p-Wert ist also extrem klein, weit unterhalb jeglicher Standards für das Signifikanzniveau (\(p << \alpha\)) und zeigt uns damit ein statistisch signifikantes Testresultat an.

Vorsicht: Die Angabe alternative hypothesis: true mean is not equal to 0 können wir zunächst ignorieren. Sie klingt zwar ein wenig wie ein Testergebnis, ist allerdings nur ein Hinweis, ob ein gerichteter oder ein ungerichteter Test (wie in diesem Beispiel) durchgeführt wurde. Auch im Fall eines nicht-signifikanten Testausgangs erscheint exakt dieselbe Angabe. Sie ändert sich also nicht in Abhängigkeit des Testausgangs, sondern nur dann, wenn wir einen gerichteten Test durchführen (siehe Abschnitt 2.4)!

Abschließend steht nach der Angabe des Konfidenzintervalls (siehe separate VL-Einheit) noch der Mittelwert der Stichprobe (hier: mittlere Differenz der Lacrosse-Scores in der Stichprobe). Dieser Wert entspricht übrigens auch dem geschätzten Mittelwert der pre-post Diferenzen der Scores für die Population, aus der unsere Stichprobe stammt.

2.3.2 Version 2: Differenz durch die Funktion t.test() berechnen lassen

Hier ist die Differenzrichtung nicht intuitiv zu erkennen. Gibt man t.test(x,y) an, werden die Differenzen als \(x - y\) berechnet. Abgesehen von einer leicht anderen Vorgehensweise bei der Testdurchführung entsteht natürlich exakt dasselbe Testergebnis.

pairedTT2 <- t.test(U60$lacrosse_post, U60$lacrosse_pre, paired = TRUE)
print(pairedTT2)

    Paired t-test

data:  U60$lacrosse_post and U60$lacrosse_pre
t = 8.4397, df = 75, p-value = 1.736e-12
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
 0.7287769 1.1791179
sample estimates:
mean difference 
      0.9539474 

2.3.3 Version 3: Formelschreibweise

Um die Formelschreibweise nutzen zu können, muss der Datensatz in ein “langes” Format gebracht werden, so dass alle Messwerte (die abhängige Variable, AV) in einer Spalte und die zugehörige Messbedingung (unabhängige Variable, UV) in einer zweiten Spalte erscheint. Die Bildung der Wertepaare wird dann automatisch über die Reihenfolge der Werte erreicht, die ja zuvor gegeben war und beim stack()-Befehl erhalten bleibt. Allerdings werden fehlende Werte (NA) in dieser Variante problematisch, so dass wir alle Probanden mit fehlenden Werten bereits vor dem stack()-Befehl aus den Daten eliminieren sollten.

##Vorsicht In vielen Fällen klinischer Studien sollte man derartige Operationen nicht unbedacht durchführen und unvollständige Daten nicht einfach löschen und außer Betracht lassen. Oftmals ist gerade die Frage, bei welchen Probanden ein follow-up Messzeitpunkt fehlt, von enormer Bedeutung für die Evaluation der Intervention. Wir werden uns diesem Problem im Kontext des Umgangs mit fehlenden Werten in klinischen Studien noch genauer widmen.

Die Schreibweise ist so zu formulieren, dass AV ~ UV entsteht. Die Differenzbildung erfolgt durch die Sortierreihenfolge der Faktorvarable in UV in der Form 1-2, also in umgekehrter Richtung wie es in den beiden oberen Fällen erfolgt ist! Man beachte das Vorzeichen des t-Werts sowie der errechneten mittleren Differenz!

# Datensatz in langes Format bringen
U60 <- U60[complete.cases(U60),]
U60L <- stack(U60, select=c("lacrosse_pre", "lacrosse_post"))
colnames(U60L) <- c("Score", "Messbedingung")

pairedTT3 <- t.test(Score ~ Messbedingung, data=U60L, paired=TRUE)
print(pairedTT3)

    Paired t-test

data:  Score by Messbedingung
t = -8.4397, df = 75, p-value = 1.736e-12
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
 -1.1791179 -0.7287769
sample estimates:
mean difference 
     -0.9539474 

2.4 Testrichtung angeben: einseitiger Test

Bis hier her haben wir einen zweiseitigen Test berechnet, welcher unsere Vermutung, dass sich das Training positiv auf die Lacrosse-Scores auswirkt, ignoriert. Wir haben lediglich getestet, ob sich irgendeine Veränderung einstellt, nicht ob diese positiver Natur ist.

Um dies zu tun, müssen wir eine Testrichtung angeben. Wir erreichen dies in der Funktion t.test() mit der Angabe alternative. Dies gibt die Richtung der Alternativhypothese an. Im klassischen Fisher-NHST ist diese nicht zwingend formuliert, sondern einfach das Gegenteil der Nullhypothese.

Vermuten wir also eine Verbesserung der Scores durch das Training, geben wir direkt diese Hypothese als alternative an, im konkreten Fall also die Verbesserung der Scores. Wenn die Differenz so berechnet wird, dass eine Verbesserung mit positiven Differenzen einhergeht (Achtung: Differenzrechnung beachten!), dann kann alternative="greater" gesetzt werden.

Im Fall 3, wo die Differenzbildung in umgekehrter Form erfolgt, erwarten wir negative Differenzen, müssen also alternative="less" setzen.

t.test(U60$lacrosse_post, U60$lacrosse_pre, paired = TRUE, alternative = "greater")

    Paired t-test

data:  U60$lacrosse_post and U60$lacrosse_pre
t = 8.4397, df = 75, p-value = 8.681e-13
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.7657017       Inf
sample estimates:
mean difference 
      0.9539474 
t.test(Score ~ Messbedingung, data=U60L, paired=TRUE, alternative="less")

    Paired t-test

data:  Score by Messbedingung
t = -8.4397, df = 75, p-value = 8.681e-13
alternative hypothesis: true mean difference is less than 0
95 percent confidence interval:
       -Inf -0.7657017
sample estimates:
mean difference 
     -0.9539474 

Wir sehen, dass im Fall eines einseitigen Tests der p-Wert noch kleiner wird und das Signifikanzlevel noch deutlicher unterschreitet. Das liegt daran, dass im einseitigen Test der gesamte kritische Bereich der Ablehnung der Nullhypothese auf eine Seite der t-Verteilung wandert, und damit auch die Frage, wie wahrscheinlich eine Ausprägung des vorgefundenen Stichprobenmittels unter Annahme der Nullhypothese ist, mit dem Flächenanteil an einem Ende der Verteilung zu beantworten ist. Da die t-Verteilung symmetrisch zur Mitte ist, halbiert sich dadurch der p-Wert aus dem zweiseitigen Test.

3 t-Test für zwei Stichproben

Wir nutzen wieder dasselbe Beispiel wie in der Vorlesung und prüfen den Gruppenunterschied zwischen den Altersgruppen unter 60 (unter60) und über 65 (ueber65) hinsichtlich der Lacrosse-Testergebnisse im Messzeitpunkt pre.

3.1 Datensatz bilden

unter60 <- MODALIS$lacrosse_pre[MODALIS$gruppe == "E" & MODALIS$alter <= 60]
ueber65 <- MODALIS$lacrosse_pre[MODALIS$alter >= 65]


# Datensatz im langen Format erzeugen
Senioren <- data.frame(Score = c(unter60, ueber65),
                       Gruppe = c(rep("unter60", length(unter60)),
                                  rep("ueber65", length(ueber65))))

Senioren$Gruppe <- as.factor(Senioren$Gruppe)
1
Verbinden der beiden Vektoren der Testscores aus beiden Gruppen zu einem langen Vektor.
2
Erzeugen der Gruppenzugehörigkeitsvariable durch sequentielles Wiederholen des jeweiligen Gruppenidentifikators (Textbaustein), in Abhängigkeit der Länge der jeweiligen Vektoren. Achtung: hierdurch enttsteht zunächst nur eine Textvariable (Datentyp character).
3
Umwandlung der Gruppenvariable von Datentyp character in eine Faktorvariable.

3.2 Prüfung der Testvoraussetzungen

Im Fall des t-Tests für zwei Stichproben kann keine Prüfung auf Normalverteilung einer Differenzvariable erfolgen. Daher sollten beide Gruppen separat auf Normalverteilung der Stichprobendaten geprüft werden.

Wir können dies entweder wieder grob visuell per Histogramm vornehmen, oder aber den Shapiro-Wilk-Test in jeder der beiden Gruppen durchführen:

hist(unter60)
hist(ueber65)
shapiro.test(unter60)
shapiro.test(ueber65)


    Shapiro-Wilk normality test

data:  unter60
W = 0.97245, p-value = 0.05745

    Shapiro-Wilk normality test

data:  ueber65
W = 0.98437, p-value = 0.1935

Das Testergebnis des Shapiro-Wilk-Tests für die Gruppe unter60 kratzt an der kritischen Grenze von \(\alpha=0.05\), unterschreitet sie aber noch nicht. Die Voraussetzung für einen t-Test ist also immer noch erfüllt.

Bei t-Tests für zwei unabhängige Gruppen sollten neben der Normalverteilung der Stichprobendaten in beiden Gruppen die Daten zudem varianzhomogen sein, d. h. in etwa gleiche Steruungen in beiden Gruppen aufweisen.

Dies kann durch die Anwendung des Bartlett-Tests (bereits enthalten in R) oder aber durch den Levene-Test (hier wäre das Zusatzpaket car erforderlich, lassen wir an dieser Stelle weg) bewerkstelligt werden. Wie auch im Fall des Shapiro-Wilk-Tests auf Normalverteilung gilt: wird der Bartlett-Test (oder der Levene-Test) statistisch signifikant, weichen die Varianzen der Gruppen voneinander ab und die Voraussetzungen des t-Tests sind verletzt.

bartlett.test(Score ~ Gruppe, data=Senioren)

    Bartlett test of homogeneity of variances

data:  Score by Gruppe
Bartlett's K-squared = 0.32639, df = 1, p-value = 0.5678

Auch hier erkennen wir ein nicht-signifikantes Testergebnis, die Voraussetzungen für den t-Test sind also erfüllt.

Alternative: Welch-Test

Für den Fall ungleicher Varianzen in beiden Gruppen hat R allerdings eine Lösungsmöglichkeit eingebaut: die Welch-Korrektur des t-Tests. Diese wird sogar standardmäßig eingesetzt, es sei denn man deaktiviert sie bewusst. Man muss var.equal=TRUE setzen, wenn man die Welch-Korrektur für ungleiche Varianzen bewusst weglassen möchte. Allerdings hat sich diese Korrektur mittlerweile sehr gut bewährt, richtet auch bei varianzhomogenen Daten keinen “Schaden” an und wird daher in R bei t-Tests für unabhängige Stichproben durch die Standardeinstellung var.equal=FALSE umgesetzt. Man erkennt die Art der Nutzung auch an der Ausgabe des Ergebnisses. Wir werden uns beide Varianten am Ende im direkten Vergleich ansehen.

3.3 Durchführung des t-Tests

Wie im obigen Fall können wir den Test auf mehrere Arten durchführen. Option 1 scheidet natürlich aufgrund zweier Stichproben aus. Allerdings kann man sowohl mit zwei getrennten Vektoren als auch mit einem data.frame im langen Format operieren.

Achtung

Im Gegensatz zum obigen Beispiel des Einstichproben-t-Tests nutzen wir nun gleich die Möglichkeit einer einseitigen Testung mit gerichteter Null- bzw. Alternativhypothese.

3.3.1 Variante 1: t-Test für zwei Stichproben: Nutzung von zwei Vektoren

Auch hier gilt: die Differenzbildung erfolgt analog zur Reihenfolge der Variablen. Die Angabe t.test(x,y) führt zur Differenzbildung \(\bar{x}-\bar{y}\). Für das Beispiel der Lacrosse-Scores und einer Hypothese, dass ältere Probanden geringere Scores zeigen, definieren wir die Alternativhypothese als greater, da wir eine positive Differenz zwischen den Mittelwerten erwarten (\(\bar{x}_{unter60} - \bar{x}_{ueber65} > 0\)).

TT1 <- t.test(unter60, ueber65, paired=FALSE, var.equal = TRUE, alternative = "greater")
print(TT1)

    Two Sample t-test

data:  unter60 and ueber65
t = 0.31614, df = 203, p-value = 0.3761
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
 -0.1740693        Inf
sample estimates:
mean of x mean of y 
 2.295114  2.253932 

3.3.2 Variante 2: t-Test für zwei Stichproben: data.frame (Langformat) und Formelschreibweise

Dasselbe Ergebnis erhalten wir durch Nutzung der Formelschreibweise in einem data.frame mit langem Datenformat. Auch hier gilt wie im Einstichproben-t-Test mit Formelschreibweise: die Richtung der Differenzbildung ist hier zunächst nicht klar erkennbar. Sie hängt von der Sortierreihenfolge der Levels der Gruppierungs- bzw. Faktorvariable ab. in unserem Fall sortieren sich die Levels alphabetisch, so dass als erstes Faktorlevel ueber65 definiert ist. Die Differenzbildung erfolgt also in umgekehrter Form wie bei der Berechnung durch zwei separate Vektoren (vgl. Abschnitt 3.3.1), sodenn wir die Levels in ihrer Sortierreihenfolge belassen. In Konsequenz müssen wir auch die Testrichtung umkehren. Man beachte das Vorzeichen des t-Werts!

TT2 <- t.test(Score ~ Gruppe, data=Senioren, var.equal=TRUE, alternative="less")
print(TT2)

    Two Sample t-test

data:  Score by Gruppe
t = -0.31614, df = 203, p-value = 0.3761
alternative hypothesis: true difference in means between group ueber65 and group unter60 is less than 0
95 percent confidence interval:
      -Inf 0.1740693
sample estimates:
mean in group ueber65 mean in group unter60 
             2.253932              2.295114 
Ergebnisinterpretation

Wir erkennen in beiden Fällen erkennen wir identische Ergebnisse, die durch die unterschiedliche Reihenfolge der Variablen in der Differenzbildung lediglich ein anderes Vorzeichen im t-Wert erzeugen. Durch die Symmetrie der t-Verteilung sind diese Ergebnisse aber äquivalent und führen auch zu identischen Schlussfolgerungen, die Nullhypothese in diesem Fall nicht abzulehnen (Ergebnisse sind statistisch nicht signifikant, da \(p > \alpha\)).

3.4 Vergleich mit und ohne Korrektur ungleicher Varianzen

Will man den t-Test nicht in der klassischen, sondern in der auf ungleiche Varianzen zwischen den Gruppen korrigierten Form (“Welch-Test”) durchführen, lässt man das Argument var.equal entweder einfach weg und generiert dadurch die Standardeinstellung var.equal=FALSE. Natürlich kann man diese Einstellung auch explizit in den Funktionsaufruf hineinschreiben:

TT1.welch <- t.test(unter60, ueber65, paired=FALSE, var.equal = FALSE, alternative = "greater")
print(TT1.welch)

    Welch Two Sample t-test

data:  unter60 and ueber65
t = 0.31873, df = 192.82, p-value = 0.3751
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
 -0.1723672        Inf
sample estimates:
mean of x mean of y 
 2.295114  2.253932 

Wir erkennen ein – in diesem Fall – nahezu identisches Ergebnis. Das hat den Grund, dass wir recht große Stichproben mit annähernd gleichen Varianzen nutzen.

Tipp

Die Ergebnisse würden deutlicher voneinander abweichen, wären die Stichproben kleiner und die Unterschiede in den Streuungen zwischen den Gruppen größer. In einem solchen Fall kann es vorkommen, dass der Welch-Test kein signifikantes Ergebnis liefert, obwohl der unkorrigierte t-Test dies tut. Im Zweifel daher immer den korrigierten t-Test (Welch-Test) durchführen.

Tutorials im Web:


Stand: 2024-01-12