Vierde beweging · Verschil onthechten

Oefening 9.2 · De t-toets

Twee gemiddelden vergelijken, gepaard of onafhankelijk · paired & independent t-test

Data bij deze oefeningpenguins.csv 342 pinguïns · slaap_middelen.csv slaapmiddelen, 1905 · diamantjes.csv de twaalf steentjes uit het boek · wat elke kolom betekent

prikkel

Twee raadsels over één woord: verschil

verschil tussen twee gemiddelden · echt of toeval

Twee kleine raadsels, allebei over hetzelfde woord: verschil.

Het eerste is meer dan honderd jaar oud.1 Tien mensen krijgen twee nachten lang elk een ander slaapmiddel, en iemand meet hoeveel uur extra slaap ze ervan krijgen. Middel A levert gemiddeld 0.75 uur op, middel B 2.33 uur. Middel B wint dus met 1.58 uur. Maar het zijn er maar tien, en mensen slapen de ene nacht nu eenmaal anders dan de andere. Is die 1.58 uur een echt verschil tussen de middelen — of hadden we gewoon een paar goede nachten voor B?

Het tweede raadsel staat op een rots bij Antarctica.2 Gentoo-pinguïns wegen gemiddeld 5076 gram, Adélies 3701 gram. Dat is 1375 gram verschil — anderhalve kilo, een flink beest lichter. Maar we hebben niet álle pinguïns gewogen, alleen degene die we toevallig oppakten. Is die 1375 gram het échte soortverschil, of hadden we pech (of geluk) met wie er in onze armen belandde?

Dezelfde vraag, twee keer: bestaat het verschil echt, of danst het op toeval? En let straks op iets moois — bij de pinguïns wordt het antwoord zó overweldigend dat de interessante vraag verschuift. Trek even mee.

speel het

Draai allebei de t-toetsen

gepaard versus onafhankelijk · t · p · 95%-CI

OpmerkingEerst zoals in het boek — de twaalf diamantjes
d <- read.csv("diamantjes.csv")

# twee merken vergelijken op glans
t.test(glans ~ merk, data = d, var.equal = TRUE)
# t(10) = -1.73   p = .114

lm(), t.test() en aov() zijn in beide talen precies dezelfde functie — daar valt niets te vertalen. Het verschil tussen base R en dplyr zit in het klaarzetten van de data, niet in het model.

Golfje tegen sterretje: t(10) = −1.73, p = .11. Het verschil is met het blote oog te zien, maar de toets zegt: bij twaalf steentjes kan dit ook toeval zijn. Onthoud die −1.73 — hij komt in de volgende twee oefeningen nog terug. In de vórige oefening stond hij er trouwens ook al, met een plus ervoor: daar was het golfje het vertrekpunt, dus rekende de dummy sterretje mín golfje. Zelfde toets, andere richting.

Blijf nog even bij die schakelaar var.equal = TRUE hangen, want daar zit meer onder dan een instelling. Stel dezelfde vraag twee keer — één keer als toets, één keer als regressie:

OpmerkingIn R · dezelfde som, twee keer opgeschreven
t.test(glans ~ merk, data = d, var.equal = TRUE)
#   Two Sample t-test
# t = -1.7321, df = 10, p-value = 0.1139

summary(lm(glans ~ merk, data = d))
#                 Estimate Std. Error t value Pr(>|t|)
#   merksterretje   20.000     11.547   1.732 0.113937

Niet ongeveer hetzelfde — dezelfde t, dezelfde tien vrijheidsgraden, dezelfde p. Alleen het teken draait om: t.test rekent hier golfje mín sterretje, en de dummy rekent sterretje mín golfje. Dat is dezelfde spiegeling als in de vorige oefening, en verder verandert er niets.

Een t-toets op twee groepen lijkt dus niet op een regressie: het ís er een. Je voorspelt de glans uit één voorspeller, het merk, en dan houd je n − 2 = 10 vrijheidsgraden over — precies waar de toets mét var.equal = TRUE zelf ook op uitkomt, want n1 + n2 − 2 = 6 + 6 − 2 = 10. Twee routes, dezelfde som.

Haal die schakelaar nu eens weg, dan draait R zijn eigen standaard. Vraag er meteen de twee spreidingen bij:

OpmerkingIn R · en dan zonder die schakelaar
t.test(glans ~ merk, data = d)
#   Welch Two Sample t-test
# t = -1.7321, df = 8.6207, p-value = 0.1188

tapply(d$glans, d$merk, sd)
#    golfje sterretje 
#  15.49193  23.66432

R noemt in zijn eerste regel zelf welke toets hij draaide: bij de vorige stond er Two Sample t-test, hier staat Welch Two Sample t-test. De t blijft staan, maar de vrijheidsgraden zakken van 10 naar 8.62 en de p schuift van .11 naar .12. Welch neemt namelijk niet aan dat de twee merken even veel spreiden — en kijk maar, dat doen ze ook niet: 23.66 tegen 15.49, ruim anderhalf keer zo breed. Die voorzichtigheid betaal je in vrijheidsgraden, en aan die gebroken 8.62 zie je dat je betaald hebt.

Overal in deze boekjes lezen we Welch, want hij is voorzichtiger en je hoeft er niets voor te kiezen. Bij deze twaalf steentjes niet, en dat is met opzet: van Welch bestaat geen gewone regressie-versie, en dit is de plek waar we die twee juist gelijk willen zien vallen. Bij de pinguïns hieronder staat Welch dus gewoon weer aan. Doe je zo’n toets ooit in JASP of SPSS, dan begint het programma daar op de rij die wél gelijke spreiding aanneemt, en vraagt je eigen vak je misschien om eerst Levene’s toets te lezen en dán een rij te kiezen — dat hoeft van ons niet, want wij lezen altijd Welch.

Nu jij — twee keer, want er zijn twee soorten t-toets. De pinguïns ken je; de slaapmiddelen van 1905 zijn nieuw, en die zijn juist bedoeld om het verschil tussen de twee toetsen te laten voelen.

Twee raadsels, twee toetsen — en het verschil zit in het design. Bij de slaapmiddelen meten we dezelfde tien mensen twee keer; die twee kolommen horen per rij bij elkaar. Dat vraagt een gepaarde t-toets (paired). Bij de pinguïns hebben we twee losse groepen dieren, geen koppels — dat vraagt een onafhankelijke t-toets (independent). Doe ze allebei.

OpmerkingIn R · trek aan de slaapmiddelen (gepaard)
slaap <- read.csv("slaap_middelen.csv")

mean(slaap$slaap_middelA)                                  # → 0.75 uur
mean(slaap$slaap_middelB)                                  # → 2.33 uur

t.test(slaap$slaap_middelA, slaap$slaap_middelB, paired = TRUE)
# verschil A - B = -1.58 u,  t(9) = -4.06,  p = .003
# 95%-CI [-2.46, -0.70]

Het min-teken zegt alleen dat A mínder oplevert dan B; de grootte is 1.58 uur. De p van .003 zegt: als de twee middelen in werkelijkheid even goed waren, zou je zó’n verschil bij tien mensen zelden per ongeluk tegenkomen. En dat interval [−2.46, −0.70] is eerlijker dan de p: het beste dat je over het echte verschil durft te zeggen is “ergens tussen 0.70 en 2.46 uur in B’s voordeel”. Klein onderzoek, breed interval — het interval is meteen zijn eigen slag om de arm.

OpmerkingIn R · trek aan de pinguïns (onafhankelijk)
peng <- read.csv("penguins.csv")
ga   <- peng[peng$soort %in% c("Gentoo", "Adelie"), ]   # twee soorten

tapply(ga$gewicht, ga$soort, mean)                       # Adelie 3701, Gentoo 5076

# var.equal = FALSE is de standaard, en dat is de Welch-toets
t.test(gewicht ~ soort, data = ga, var.equal = FALSE)
# verschil ~ 1375 g,  t = -23.39,  p < .001
# 95%-CI van het verschil ~ [1260, 1491] g

Kijk nog eens naar de twee stukjes code hierboven, want ze verschillen op iets wat je makkelijk mist. Bij de slaapmiddelen geef je twee kolommen mee (slaap$slaap_middelA, slaap$slaap_middelB) — die tabel staat wide, één rij per persoon. Bij de pinguïns geef je een formule mee (gewicht ~ soort) — die staat long, één rij per dier met een kolom die de groep noemt. Wil je de tien slaapkoppels als lijntjes plotten, dan moet die tabel eerst kantelen; hoe dat gaat, staat bij wide en long.

Kijk eens naar die t van −23.39. Bij de slaapmiddelen was het −4.06 en dat vonden we al overtuigend; hier is-ie bijna zes keer zo groot. De p is zó klein dat R ’m niet eens meer voluit schrijft (< 2.2e-16). Onthoud dat cijfer even — in “Snap het” blijkt het minder indrukwekkend dan het lijkt.

schud het

Duizend werelden waarin de waarheid nul is

labels husselen · teken omgooien · toeval-bergje rond nul

Nu de vraag die telt: bestaat het verschil écht? We gaan het toeval nabouwen. De truc is telkens dezelfde, en hij is mooi: we bouwen duizend werelden waarin de waarheid nul is — waarin er per definitie géén verschil bestaat — en kijken hoe ver puur geluk het gemeten verschil dan tóch van nul wegtrekt. In geen enkele van die werelden meet je precies nul; het toeval laat het verschil dansen om nul. Die dans is een bergje. Ligt jouw echte verschil ín het bergje, dan kan toeval het verklaren. Ligt het erbuiten, dan is het echt.

Bij de pinguïns bouw je die nul-werelden door de soort-labels te husselen. Je houdt alle gewichten precies zoals ze zijn, maar je plakt er lukraak “Gentoo” of “Adélie” op. In zo’n wereld zegt de soort niets meer over het gewicht — het echte soortverschil is nul. En dan meet je toch, elke keer, een verschil, puur door wie er toevallig welk label kreeg.

OpmerkingIn R · hussel de soort-labels (1000 nul-werelden)
echt <- mean(ga$gewicht[ga$soort == "Gentoo"]) -
        mean(ga$gewicht[ga$soort == "Adelie"])            # 1375 g

set.seed(42)
nul <- replicate(1000, {
  door_elkaar <- sample(ga$soort, replace = FALSE)         # labels husselen
  mean(ga$gewicht[door_elkaar == "Gentoo"]) -
  mean(ga$gewicht[door_elkaar == "Adelie"])
})

hist(nul, xlim = c(-500, 1500))                            # het toeval-bergje rond 0
abline(v = echt, col = "red", lwd = 2)                     # en dáár staat 1375
range(nul)                                                 # → ongeveer -386 tot 367

Kijk naar dat bergje. Duizend werelden waarin soort er niet toe doet, en het toeval komt niet verder dan zo’n 386 gram van nul — een klein beetje geschommel. En dan die rode streep op 1375, kilometers rechts van het hele bergje. Geen enkele van de duizend nul-werelden haalt jouw verschil, of komt zelfs maar in de buurt. Dát is “geen toeval”: geen p-waarde die je moet geloven, maar een afstand die je zíet.

Bij de slaapmiddelen hoort een ándere schud-zet, want het design is anders. Daar zijn geen twee groepen om te husselen — er zijn tien personen, elk met hun eigen verschil (A minus B). De nul-wereld is hier: het maakt niet uit welk middel je A en welk je B noemt. Dus voor elke persoon gooien we een muntje dat bepaalt of zijn verschil met een plus of een min meetelt. Duizend keer.

OpmerkingIn R · draai per persoon het teken (1000 nul-werelden)
verschil <- slaap$slaap_middelA - slaap$slaap_middelB      # 10 verschillen
echt_gem <- mean(verschil)                                 # -1.58 u

set.seed(42)
nul <- replicate(1000, {
  munt <- sample(c(-1, 1), length(verschil), replace = TRUE)
  mean(verschil * munt)                                    # teken lukraak omgooien
})

hist(nul, xlim = c(-2, 2))                                 # bergje rond 0
abline(v = echt_gem, col = "red", lwd = 2)                 # -1.58 aan de rand

▶ Zie het dansen: het schud-speeltje

Ook hier danst het toeval om nul, en de echte −1.58 uur ligt aan de uiterste rand — met tien muntjes komt het geluk daar bijna nooit. Twee designs, twee manieren van husselen, één idee: duizend werelden waarin de waarheid nul is, maar het gemeten verschil nooit precies nul. De toets vertelt je hoe raar jouw verschil zou zijn als er niks was.

snap het

Echt is niet hetzelfde als belangrijk

effectgrootte · Cohens d · significantie en steekproefgrootte

Allebei de verschillen zijn dus echt, geen toeval. Maar “echt” is niet hetzelfde als “belangrijk”, en juist de pinguïns laten dat scherp zien.

Herinner je die t van −23.39 en de p die niet meer op het scherm paste? Die duizelingwekkende getallen betekenen niet dat het pinguïn-verschil belangrijker is dan het slaap-verschil. Ze zijn zo groot om twee saaie redenen: het verschil is bruut (anderhalve kilo) én we hebben veel dieren (274 stuks). Een t-toets straft kleine steekproeven af en beloont grote; gooi er genoeg waarnemingen in en zelfs een schamel verschil wordt “hoogsignificant”. Bij een groot, duidelijk verschil met een royale N is significantie triviaal — de toets bevestigt alleen wat je met het blote oog al zag. De interessante vraag is dan niet óf er verschil is, maar hoe groot.

Daarvoor bestaat de effectgrootte (effect size) — een verschil losgemaakt van de steekproefgrootte. Voor twee groepen is dat Cohens d: het verschil uitgedrukt in standaarddeviaties.

OpmerkingIn R · hoe groot is groot? (Cohens d)
# Cohens d: verschil in gewicht, gedeeld door de gepoolde spreiding
# install.packages("effectsize")   # eenmalig, als je 'm nog niet hebt
library(effectsize)                # of reken 'm met de hand uit de SD's
cohens_d(gewicht ~ soort, data = ga)      # → d = -2.87  (Adelie min Gentoo)

d = 2.87. Dat is enorm — de twee soorten liggen bijna drie standaarddeviaties uit elkaar; wijs een willekeurige Gentoo en een willekeurige Adélie aan en de Gentoo is vrijwel altijd zwaarder. Dáár zit het echte verhaal, niet in de t.

En de slaapmiddelen, met hun bescheiden N van 10? De effectgrootte voor een gepaard verschil heet dz, en die is hier −1.28 — ook fors. Het verschil tussen A en B is meer dan één standaarddeviatie groot. Klein onderzoek, maar geen klein effect. Precies het omgekeerde plaatje van de pinguïns: daar was de t spectaculair en het nieuws de grootte; hier is de t bescheiden en is de grootte nog steeds het nieuws.

En nog één ding, om de oefeningen aan elkaar te knopen. Die 1375 gram tussen Gentoo’s en Adélies heb je in de vorige oefening al zien staan, en niet als gemiddelde maar als regressiegewicht: het was daar het getal bij de Gentoo-dummy. Dezelfde vergelijking, één keer als toets en één keer als lijn. Wat de t-toets eraan toevoegt is niet het verschil zelf maar de vraag eromheen — hoe ver kan toeval dit verschil namaken?

De les van dit blok, in drie zinnen:

  • Het design kiest de toets. Dezelfde mensen twee keer gemeten → gepaard. Twee losse groepen → onafhankelijk. Dat is geen smaak maar een feit over je data.
  • Significant zegt “waarschijnlijk niet nul”, niet “groot”. Bij veel data is significantie goedkoop; laat je niet imponeren door een t van 23.
  • De grootte is de vraag die overblijft. Rapporteer altijd een effectgrootte naast de toets — d, een interval, of gewoon het verschil in gewone eenheden (uren, grammen). Dát is wat een mens wil weten.

Zou je het in één eerlijke zin opschrijven: niet “het verschil is significant (p < .001)”, maar: Gentoo’s zijn gemiddeld 1375 gram zwaarder dan Adélies (95% CI [1260, 1491]), een zeer groot effect (d = 2.87). Het getal met een maat eromheen, niet een sterretje.

jouw beurt

Dezelfde tien slapers, van twee kanten bekeken

gepaard versus onafhankelijk · persoonsverschillen · samenhang tussen twee metingen

Jouw beurt — bekende data, en een toets die je van een andere kant benadert. De les hierboven was: het design kiest de toets. Nu ga je zien wat die keuze waard is: je draait dezelfde twintig metingen twee keer, één keer zoals het hoort en één keer zoals het níét hoort, en je kijkt wat dat kost.

Zet eerst klaar, en beantwoord daarna de vragen. De laatste heet met opzet Z) en niet l): de aannames staan altijd achteraan, en die vreemde letter zegt “en ook, elke keer, deze”.

OpmerkingIn R · zet klaar
slaap    <- read.csv("slaap_middelen.csv")
verschil <- slaap$slaap_middelA - slaap$slaap_middelB
OpmerkingJouw beurt

a) Hoeveel mensen doen er mee, en hoeveel metingen heeft elk van hen? Waar in de tabel zie je dat de twee metingen bij dezelfde persoon horen? (twee getallen en één zin over de vorm van de tabel)

b) Hoeveel uur extra slaap leverden de twee middelen gemiddeld op, en hoeveel scheelt dat? (rapporteer M per middel en het verschil, in uren)

c) Schrijf de nulhypothese voor de gepaarde toets voluit op, in woorden én in symbolen. (één zin, en die ook in symbolen)

d) Draai de gepaarde toets: t.test(slaap$slaap_middelA, slaap$slaap_middelB, paired = TRUE). (rapporteer t(df), p en het 95%-interval)

e) Draai nu dezelfde twintig metingen als twee lósse groepen — dezelfde aanroep, alleen paired = TRUE weggelaten. (rapporteer t, df, p en het 95%-interval)

f) Vergelijk d) en e). Eén getal is in beide toetsen precies hetzelfde. Welk, en wat is er dan wél veranderd? (één getal, en wat de twee intervallen verschillend doen)

g) Reken drie spreidingen uit: die van middel A, die van middel B, en die van de tien persoonsverschillen. (drie getallen)

h) Reken de samenhang tussen de twee metingen uit met cor(slaap$slaap_middelA, slaap$slaap_middelB). (rapporteer r)

i) Leg g) en h) naast elkaar en verklaar waarom de gepaarde t ruim twee keer zo groot is. (één breuk in woorden: wat staat er boven en wat onder de streep)

j) Kijk naar de tien verschillen zelf. Hoeveel mensen sliepen er beter op B, hoeveel beter op A, en hoeveel precies even lang? (drie getallen)

k) Welke van de twee toetsen liegt hier? En stel dat die samenhang géén .80 was maar ongeveer nul — wat zou er dan met de spreiding van de tien verschillen gebeuren, en dus met het verschil tussen de twee p’s? (één keuze en twee gevolgen)

Z) Mag je alles hierboven geloven? De gepaarde t-toets leunt op één aanname, en die gaat niet over de twee kolommen maar over de tien verschillen. Welke is dat, en houdt hij hier stand? Kijk naar de tien getallen zelf. (één aanname, en het getal in de rij dat je aan het twijfelen brengt)

a) 10 mensen, elk 2 keer gemeten. Je ziet het aan de vorm van de tabel: er staat één rij per persoon met twee kolommen ernaast. Die twee getallen op één rij horen bij hetzelfde mens — dát is wat “gepaard” betekent.

b) Middel A gaf M = 0.75 uur extra slaap, middel B M = 2.33 uur. B wint met 1.58 uur.

c) De nulhypothese: de twee middelen leveren gemiddeld evenveel extra slaap op, dus het gemiddelde verschil is in de populatie nul. In symbolen: \(H_0:\ \mu_d = 0\) tegen \(H_1:\ \mu_d \neq 0\), waarin \(d\) het verschil per persoon is. Je mag het ook als \(H_0:\ \mu_A = \mu_B\) schrijven; één van de twee is genoeg. Grieks, want het gaat over de populatie en niet over deze tien.

d) t(9) = −4.06, p = .003, 95% CI [−2.46, −0.70]. Het min-teken zegt alleen dat A mínder oplevert dan B.

e) t = −1.86, df = 17.78, p = .079, 95% CI [−3.37, 0.21].

f) Het verschil zelf: −1.58 uur, in allebei de toetsen precies gelijk. Wat er wél verandert is de onzekerheid eromheen. Het gepaarde interval loopt van −2.46 tot −0.70 en blijft aan één kant van de nul; het onafhankelijke loopt van −3.37 tot 0.21 en pákt de nul erbij. Zelfde data, zelfde verschil, ander oordeel.

g) SD(A) = 1.79, SD(B) = 2.00, SD(verschil) = 1.23. De tien verschillen spreiden dus mínder dan de twee kolommen waar ze uit komen.

h) r = .80. Wie makkelijk slaapt, sliep op állebei de middelen veel; wie ligt te woelen, op allebei weinig.

i) Een t is een verschil gedeeld door een spreiding. Boven de streep staat in allebei de toetsen dezelfde −1.58. Onder de streep niet: de gepaarde toets rekent met de spreiding van de tien verschillen (1.23) en komt op een standaardfout van 0.39, de onafhankelijke rekent met de twee losse spreidingen (1.79 en 2.00) en komt op 0.85. Deel hetzelfde getal door iets kleiners en er komt een grotere t uit — vandaar −4.06 tegen −1.86. Wat de onafhankelijke toets weggooit, is precies die r van .80.

j) Negen van de tien sliepen beter op B, niemand beter op A, en één precies even lang. Dat is het concreetste bewijs dat er iets te koppelen valt: negen van de tien wijzen dezelfde kant op, hoe verschillend die mensen onderling ook slapen.

k) De onafhankelijke liegt. Die doet alsof de twintig metingen van twintig verschillende mensen komen, en dat is niet zo. Lag de samenhang rond nul, dan zou de spreiding van de verschillen niet 1.23 zijn maar ongeveer 2.69 — de twee losse spreidingen die dan niets van elkaar afhalen — en dan lopen de twee toetsen bijna gelijk. De winst van het gepaarde design zit dus niet in de toets maar in de samenhang: hoe sterker de twee metingen samenhangen, hoe meer je eraan hebt.

Z) Hadden we zomaar een gepaarde t-toets mogen doen? Wat is de aanname? Dat de verschilscores normaal verdeeld zijn — niet de twee kolommen. Zijn déze verschilscores normaal verdeeld? Nee — geen enkele steekproef is precies normaal verdeeld. Maar dat is de aanname ook niet: de aanname is dat de verschilscores normaal verdeeld zijn in de populatie waar ze uit komen.

En hier is het eerlijke antwoord: hij wankelt. Kijk naar de rij — −1.2 −2.4 −1.3 −1.3 0.0 −1.0 −1.8 −0.8 −4.6 −1.4. Negen getallen liggen tussen 0 en −2.4, en dan is er één van −4.6. Die ene trekt de rij scheef, en bij tien waarnemingen weegt hij zwaar.

Wat dat kost, en wat niet: haal je die persoon weg, dan wordt de uitkomst sterker, niet zwakker — t = −5.66 met p < .001 in plaats van t = −4.06 met p = .003. De conclusie draait dus niet om. Maar dat had je niet kunnen weten zonder te kijken, en dat is het hele punt van deze vraag: je zou het eigenlijk even moeten toetsen.

Zelfde vorm in het boek

Hier: twee groepen (of twee metingen), één verschil, en de vraag of dat verschil het toeval overleeft — plus hoe groot het eigenlijk is.

In het boek: W6 — Bestaat het verschil echt?

Daar komt de toets pas ná het interval en na de simulatie: eerst vóélen hoe ver toeval reikt, dan pas de vraag “stel dat er niks was”.

Voetnoten

  1. Cushny & Peebles (1905), het klassieke slaapmiddelen-experiment — dezelfde data waarop Student in 1908 zijn t-verdeling demonstreerde. slaap_middelen.csv, 10 personen. Alle getallen nagerekend.↩︎

  2. Palmer Penguins — Gorman, Williams & Fraser (2014), Palmer Station Antarctica LTER; via het R-pakket palmerpenguins (CC0). penguins.csv. Alle getallen op die échte data nagerekend.↩︎