Derde beweging · Verschil op de proef
Oefening 6.1 · De p-waarde
Toetsen tegen de nulhypothese, en de p zelf tellen · the p-value
In deze oefening
Data bij deze oefening — plantgroei.csv plantgroei onder drie condities · diamantjes.csv de twaalf steentjes uit het boek · wat elke kolom betekent
prikkel
Een half grammetje meer
verschil tussen gemiddelden · toeval als verklaring
Dertig planten, drie potjes voer.1 Tien krijgen niks bijzonders (controle), tien krijgen het ene goedje, tien het andere. Aan het eind weeg je van elke plant het droge gewicht. De controle-planten wegen gemiddeld 5.03 gram, de planten op behandeling 2 gemiddeld 5.53. Een half grammetje meer.
Doet het voer iets? Of is dat halve grammetje gewoon toeval — hadden er nou eenmaal een paar zware planten in het verkeerde potje gestaan?
Dat is de vraag onder bijna élk onderzoek. En het antwoord komt straks in één klein getalletje: p = .048. In dit blok gaan we dat getal niet geloven — we gaan het tellen.
speel het
Laat de t-toets het verschil wegen
t · p · betrouwbaarheidsinterval · significantiegrens .05
d <- read.csv("diamantjes.csv")
# de p van de helling staat in de summary, niet in lm zelf
model.karaat <- lm(glans ~ karaat, data = d)
summary(model.karaat)
# helling: b = 32.14 p = .049lm(), 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.
De helling van karaat op glans komt uit op p = .049 — nét onder de .05, met de hakken over de sloot. Precies zulke randgevallen laten zien wat een p-waarde wel en niet is: geen keurmerk, maar een kans onder een aanname.
Nu jij — dezelfde plantjes als in de vorige oefening. Je kent het verschil al; nu vraag je hoe vaak toeval zoiets maakt.
Haal de planten binnen en laat de klassieke t-toets het verschil wegen tussen controle en behandeling 2.
pg <- read.csv("plantgroei.csv")
# gemiddeld gewicht per groep
tapply(pg$gewicht, pg$groep, mean) # controle 5.03, behandeling2 5.53
# vergelijk controle vs behandeling2
tweetal <- pg[pg$groep %in% c("controle", "behandeling2"), ]
# FALSE is de standaard: Welch, het huismerk van deze boekjes
t.test(gewicht ~ groep, data = tweetal, var.equal = FALSE) # t = 2.13, p = 0.048Daar staat het: het verschil is 0.49 gram, t = 2.13, en p = .048. Het 95%-betrouwbaarheidsinterval loopt van 0.01 tot 0.98 — het schampt de nul, maar gaat er nét niet overheen. Volgens de gewoonte-grens van .05 is dit “significant” — nét. Maar wat ís die .048 eigenlijk? Voor je die vraag beantwoordt uit een tabel, gaan we hem zelf maken.
schud het
Duizend werelden waarin het voer niks doet
labels husselen · p als getelde fractie
Hier is de truc, en het is de mooiste van het hele boek. Stel: het voer doet niks. Helemaal niks. Dan is het etiket “controle” of “behandeling2” op een plant volstrekt willekeurig — je had de labels net zo goed door elkaar kunnen gooien, het gewicht zou hetzelfde blijven. Dus dat doen we. Duizend keer.
Elke keer husselen we de twintig groepslabels lukraak over de twintig planten, en meten we het verschil tussen de twee nep-groepen. Zo bouwen we duizend werelden waarin het voer bewijsbaar niks doet — en kijken hoe vaak het blinde toeval alléén al een verschil oplevert dat even groot is als (of groter dan) onze echte 0.49.
En let op waar déze werelden liggen: rond nul, want daar hebben we ze naartoe geknipt — precies wat de bootstrap-werelden van Oefening 5.1 níét deden, en daarom kon je uit die dans geen p tellen.
tweetal <- pg[pg$groep %in% c("controle", "behandeling2"), ]
# het echte verschil; tapply zet de groepen op alfabet, dus controle mín behandeling2
echt <- diff(tapply(tweetal$gewicht, tweetal$groep, mean)) # → -0.49
# één toeval-wereld: plak de labels lukraak op de gewichten
schud <- function() {
nep <- sample(tweetal$groep, replace = FALSE) # labels door elkaar
abs(diff(tapply(tweetal$gewicht, nep, mean))) # verschil in die wereld
}
set.seed(42)
werelden <- replicate(1000, schud())
hist(werelden) # een bergje rond nul
abline(v = abs(echt), col = "red", lwd = 2) # daar staat de echte 0.49
# tel: hoe vaak komt het toeval even ver of verder?
mean(werelden >= abs(echt)) # → 0.043▶ Zie het geteld: het schud-speeltje
Kijk naar dat plaatje. De duizend toeval-verschillen kruipen dicht om nul — de meeste werelden komen niet in de buurt van een half grammetje. En dan tel je hoe vaak het toeval tóch even ver reikt als jouw echte planten: 43 van de 1000. Dat aandeel — .043 — ís de p-waarde. Geen formule die je uit een tabel moet geloven, maar een fractie die je hebt geteld:
De p is de fractie toeval-werelden die net zo ver komen als de jouwe.
Zeldzaam is het, die 43 op 1000 — maar niet onmogelijk. Schud met een andere seed en er staat .04 of .05: duizend werelden is zélf ook maar een greep, dus het getal wiebelt een beetje. De toets hierboven gaf .048 — dezelfde boodschap, langs een andere weg. En hoe je het ook telt, het staat op het randje. Dat randje is de hele les.
snap het
Wat p = .048 wél en niet zegt
p versus effectgrootte · .05 als afspraak · afwezigheid van bewijs
Nu je p zelf geteld hebt, kun je precies zien wat het wél en niet zegt.
Wat het zegt. Onze p = .048 betekent: als het voer niks deed, zou zó’n groot verschil in maar ongeveer 5 van de 100 toeval-werelden opduiken. De data passen dus slécht bij het idee “er is niks”. Dat is precies wat een p-waarde meet — hoe slecht de data bij ‘er is niks’ passen, en niets meer.
Wat het níét zegt. Let op, want hier struikelt bijna iedereen:
- p is niet hoe groot het effect is. Ons effect is een half grammetje — dat lees je af aan het verschil (0.49) en het interval [0.01, 0.98], niet aan de p. Een piepklein effect kan een piepkleine p krijgen als je maar genoeg planten weegt.
- p is niet de kans dat er niks aan de hand is. Hij rekent de andere kant op: hij vertrekt vanuit “er is niks” en vraagt hoe raar jouw data dan zijn — niet vanuit jouw data hoe waarschijnlijk “er is niks” is. P(data | er is niks) is iets heel anders dan P(er is niks | data).
En dat randje. Onze .048 haalt de gewoonte-grens van .05 — nét. Maar bedenk: was er één zware controle-plant net iets lichter geweest, dan stond er misschien .052, en dan zou dezelfde uitkomst ineens “niet significant” heten. Dat kan niet kloppen. .05 is een afspraak, geen natuurgrens. Een p van .048 en een p van .052 vertellen hetzelfde verhaal: een zwak, wankel signaaltje dat om nuance vraagt, niet om een ja/nee-stempel.
En de andere kant op. Reken voor de grap ook eens controle tegen behandeling 1 uit:
ander <- pg[pg$groep %in% c("controle", "behandeling1"), ]
# weer Welch, weer de standaard — zodat je 'm met de vorige kunt vergelijken
t.test(gewicht ~ groep, data = ander, var.equal = FALSE) # p = 0.25 — dik niet-significantDaar komt p = .25 uit: het toeval haalt zó’n verschil moeiteloos, in een kwart van de werelden. Niks aan de hand? Voorzichtig. “Niet significant” betekent niet aangetoond — niet aangetoond dat er niks is. Misschien werkt behandeling 1 wél en waren tien planten te weinig om het te zien. Afwezigheid van bewijs is geen bewijs van afwezigheid. Een p die groot is, sluit niets uit; hij zwijgt alleen.
jouw beurt
Voer één tegen voer twee
t-toets · getelde p · wiebel van de telling
Voer één tegen voer twee, bekende data. In de oefening over het betrouwbaarheidsinterval kreeg dit paar een interval; een p voor dat verschil in gewicht heeft nog niemand geteld. Zet de twee groepen klaar en beantwoord daarna de vragen. De laatste heet Z): de aannames staan altijd achteraan, en die letter is met opzet geen volgletter.
pg <- read.csv("plantgroei.csv")
voer <- pg[pg$groep %in% c("behandeling1", "behandeling2"), ]table(voer$groep) hoort tien en tien te geven. Staat de controle er nog tussen, dan is je filter niet aangekomen.
a) Schrijf de nulhypothese en het alternatief voluit op, in woorden én in symbolen. (twee zinnen, en die twee ook in symbolen)
b) Draai de t-toets: t.test(gewicht ~ groep, data = voer). (rapporteer t, df en p)
c) Mag de nulhypothese verworpen worden bij de gewoonte-grens van .05? Zeg erbij wát je precies verwerpt. (ja of nee, en over planten, niet over getallen)
d) Lees het betrouwbaarheidsinterval erbij af, en zeg waar de nul ligt. (rapporteer het 95% CI met allebei de grenzen)
e) Tel de p nu zelf. Zelfde schud-recept als in de romp van dit blok, ander paar — zet eerst set.seed(42). (rapporteer de fractie én het aantal werelden)
# het echte verschil, zonder teken
echt <- abs(diff(tapply(voer$gewicht, voer$groep, mean)))
# duizend werelden waarin het voer niks doet
set.seed(42)
werelden <- replicate(1000, {
nep <- sample(voer$groep, replace = FALSE)
abs(diff(tapply(voer$gewicht, nep, mean)))
})
# tel hoe vaak het toeval even ver komt
mean(werelden >= echt)f) Leg je getelde fractie naast de p van de toets bij b). Vertellen ze hetzelfde verhaal? (twee getallen en één zin)
g) Vervang de 42 in set.seed() door 1 en tel opnieuw. Er komt een ander getal uit, op precies dezelfde planten. Hoe kan dat? (het nieuwe getal, en waar de wiebel vandaan komt)
h) Je hoeft niet te schudden om het echte antwoord te krijgen: je kunt álle manieren langslopen waarop twintig planten in twee tientallen uiteen kunnen vallen. Dat zijn er 184756, en dat getal hoef je niet zelf te kunnen uitrekenen. De uitkomst daarvan is .0086. Wat zegt dat over je twee getellingen bij e) en g)?
i) Wat zegt deze p niet? Noem er twee. (twee dingen, elk in één zin)
j) Schrijf de inhoudelijke conclusie, in maximaal vijf zinnen. (over de twee soorten voer, met de grootte van het verschil erin en niet alleen de p)
Z) Mag je alles hierboven geloven? De toets bij b) en de telling bij e) leunen op verschillende dingen — kijk voor de toets naar de vorm van de twintig gewichten (boxplot(gewicht ~ groep, data = voer)) en naar de twee spreidingen (tapply(voer$gewicht, voer$groep, sd)), en vraag je bij de telling af of het etiket “voer één” of “voer twee” onder de nulhypothese echt willekeurig op een plant geplakt had kunnen worden.
a) De nulhypothese: de twee soorten voer leveren gemiddeld evenveel droge plant op — het verschil dat je meet, komt dan volledig uit het toeval van welke plant in welk potje stond. Het alternatief: ze leveren niet evenveel op. In symbolen:
\[H_0:\ \mu_1 = \mu_2 \qquad H_1:\ \mu_1 \neq \mu_2\]
Grieks, want \(\mu\) is het gemiddelde in de populatie — alle planten die zo gekweekt hadden kunnen worden — en niet de 4.66 en 5.53 van deze twintig. Je mag het ook als één verschil schrijven, \(H_0:\ \mu_1 - \mu_2 = 0\); één van de twee is genoeg. En let op het \(\neq\): tweezijdig, want vooraf wist niemand wélk voer zou winnen.
b) t(14.10) = −3.01, p = .009.
c) Ja. Wat je verwerpt is het idee dat de twee soorten voer gemiddeld hetzelfde opleveren: onder díé aanname is een verschil van 0.87 gram zeldzaam genoeg om er niet in te blijven geloven. Je verwerpt niet “toeval” in het algemeen, en je bewijst ook niet dat voer twee altijd beter is.
d) 95% CI [−1.48, −0.25]. De nul valt er ruim buiten — geen geschamp deze keer, zoals bij controle tegen voer twee.
e) .006, oftewel 6 van de 1000 werelden. (Op je scherm staat 0.006; die voorloopnul haal je pas weg als je het opschrijft.)
f) .006 tegen .009. Twee wegen naar hetzelfde oordeel: dit verschil is zeldzaam in een wereld waarin het voer niets doet. Dat ze niet precies gelijk zijn is geen fout — de toets rekent met een formule, jouw telling met duizend willekeurige werelden.
g) .012, twee keer zoveel. De planten zijn niet veranderd; jouw duizend werelden wel. Duizend werelden is zélf ook maar een greep, en hoe kleiner de p die je zoekt, hoe schaarser de werelden die meetellen — bij zes tegen twaalf treffers hangt het getal aan een handvol werelden en wiebelt het dus hard. Wil je een kleine p nauwkeurig tellen, dan heb je er veel meer dan duizend nodig.
h) Dat .0086 is het antwoord waar geen toeval meer in zit: alle 184756 hersplitsingen langsgelopen, 1592 daarvan komen even ver of verder. Jouw .006 en .012 liggen er aan weerskanten omheen, en dat is precies wat je verwacht van twee grepen van duizend. Niet één van beide is “de goede” — ze zijn allebei een schatting van dit getal.
i) Twee dingen, en bij allebei struikelt bijna iedereen:
- p is niet hoe groot het effect is. Dat lees je af aan het verschil van 0.87 gram en het interval [−1.48, −0.25], niet aan de .009.
- p is niet de kans dat er niks aan de hand is. Hij vertrekt vanuit “er is niks” en vraagt hoe raar jouw data dan zijn. P(data | er is niks) is iets heel anders dan P(er is niks | data).
j) Bijvoorbeeld:
De planten op voer twee wogen gedroogd gemiddeld 5.53 gram, die op voer één 4.66 gram — een verschil van 0.87 gram in het voordeel van voer twee. Dat verschil was significant, t(14.10) = −3.01, p = .009, 95% CI [−1.48, −0.25]. Zo’n verschil kwam in maar zes van de duizend geschudde werelden voor, dus “de twee soorten voer doen hetzelfde” past slecht bij deze data. Hoe groot het verschil precies is, ligt nog ruim open: ergens tussen een kwart gram en anderhalve gram. Met tien potten per groep is dat de eerlijke marge.
Wat erin hoort: de richting, de grootte, én de onzekerheid — niet alleen dat het significant was.
Z) Ja, met een kanttekening bij de toets. De twee toetsen leunen op verschillende dingen, en dat is de les van deze vraag.
De t-toets bij b) leunt erop dat de gewichten redelijk symmetrisch liggen en dat de gemiddelden netjes rond de waarheid wiebelen. Dat valt hier goed uit; de scheefheid is 0.47 bij voer één en 0.48 bij voer twee, met tien potten per groep gewone ruis. De twee spreidingen liggen wél het verst uiteen van alle paren in dit bestand — SD = 0.79 tegen 0.44, een verhouding van 1.79 — maar het huis houdt onder de 2 aan, en de Welch-variant die R standaard draait is juist gebouwd voor ongelijke spreiding.
De schudtoets bij e) leunt op iets anders: dat de etiketten onder de nulhypothese uitwisselbaar zijn. Doet het voer niets, dan had elk etiket op elke plant gekund, en dan is husselen eerlijk. Dat is een zwaardere eis dan hij klinkt: hij zegt niet alleen dat de gemiddelden gelijk zijn, maar dat de twee groepen onder de nulhypothese in álles op elkaar lijken — ook in spreiding. Zou het ene voer de planten alleen maar wisselvalliger maken zonder het gemiddelde te raken, dan verwerpt deze toets iets wat je niet bedoelde te toetsen.
De weg terug, als het was misgegaan:
- Blijft staan: de gemiddelden en het verschil van 0.87 gram bij b) en j). Dat is optellen en delen.
- Doe je over: de p bij b) en e), en daarmee het oordeel bij c). Een scheve verdeling raakt de toets; ongelijke spreiding raakt vooral de telling.
◠ Zelfde vorm in het boek
Hier: het toeval duizend keer laten dansen om nul, en tellen hoe vaak het even ver komt als jij — dat aandeel is de p.
In het boek: W6 — Bestaat het verschil echt?
Daar wordt de toets een omkering: stel dat er niks is — hoe raar zijn onze data dán? De p is het antwoord op die omgekeerde vraag, nooit op de vraag zelf.
Voetnoten
PlantGrowth — droog gewicht van planten onder drie condities; Dobson (1983), via R (
datasets::PlantGrowth, publieke data). Alle getallen in dit blok zijn op die échte data nagerekend.↩︎