De pad zat aan zijn vijver. Het was een wateroppervlak met geheugen — een vijver die soms iets wist over wie erin keek dat de kijker zelf niet wist.
Sommige dieren bleven staan en tuurden naar zichzelf in het water. Andere liepen door zonder een blik over hun schouder. Het ene dier checkte zijn snorharen alsof er een afspraak op het spel stond. Het andere had het te druk met de geur van de wind, of was te ontspannen om zich druk te maken om zijn eigen kop.
“Twee mogelijkheden per dier,” dacht de pad. “Wel turen, of niet turen. Geen tussenstand.”
Hij vroeg zich af of er iets te voorspellen viel. Misschien dat dieren die net een afwijzing hadden gehad het water opzochten om te checken of er iets aan ze mankeerde. Misschien dat oudere dieren juist minder zelf-bekijkers waren — minder uit te zoeken, of minder bereid het uit te zoeken.
Eén ding wist hij zeker: een gewone rechte regressielijn ging hem niet helpen. Zijn uitkomst was geen continue maat — geen hoeveel, alleen wel of niet. Hij had een ander gereedschap nodig.
De techniek heet logistic regressionLRA — en in dit hoofdstuk gaan we hem stap voor stap opbouwen, te beginnen met de allereenvoudigste vraag: als ik niets over een dier weet, hoe goed kan ik dan al gokken of hij tuurt?
OpmerkingWat je na dit thema moet kunnen
Herkennen dat een binaire om LRA vraagt.
Met de hand van naar kans, odds en odds ratio rekenen, en het kantelpunt vinden.
Met de hand het -interval van en van de odds ratio uitrekenen.
Per voorspeller de Wald-toets lezen; de likelihood-ratio-toets voor het hele model of tussen twee geneste modellen.
uitrekenen uit twee deviances.
Een model in blokken opbouwen (hiërarchische LRA): per blok de -toets en per model .
Uit een classificatietabel het percentage goed, de sensitiviteit, de specificiteit, PPV en NPV halen.
Weten welke aannames je checkt en welke juist niet.
De uitkomst in een APA-zin opschrijven.
Wat dichtgeklapt staat onder Voor wie verder wil hoort hier niet bij. Wat blijft liggen, onderaan, noemt wat niet behandeld wordt.
Twee formules komen in dit thema steeds terug: de logistische vergelijking en die van .
4.0 Project- en datavoorbereiding
Aantekeningen netjes, paden kloppen
Download de bron van dit oefenboek (de zip op de voorpagina), pak hem uit en dubbelklik op mvda_werkboek.Rproj — één project voor alle thema’s. Open daarna 04_logistische_regressie/04_logistische_regressie.qmd en draai de code vanuit dat bestand: RStudio voert een chunk uit in de map van het hoofdstuk, dus de paden kloppen. De data van dit thema ligt in 04_logistische_regressie/data/, de helper-functies in common/R/. Niets te installeren als de twee pakketten (car, tidyverse) op je computer staan; anders één keer:
Per dier vier waarden: bekeek_zichzelf (0 = nee, 1 = ja), leeftijd (jaren), aantal_afwijzingen (recente sociale flops) en diersoort (ree/vos/das). De drie voorspellers vormen samen het kandidaat-model.
4.1 De pad telt — eerst met één voorspeller
Van een eenvoudige gok naar een model dat luistert naar één gegeven
“Ik begin klein,” zei de pad. “Eerst tel ik alleen wat ik zie. Dan voeg ik één ding toe. Daarna kijk ik of het beter wordt.”
In deze vijf mini-secties (4.1.a t/m 4.1.e) bouwen we het allereenvoudigste logistische model — één voorspeller, niets anders — en oefenen we kans → odds → odds ratio. Géén Wald-toets en géén likelihood-ratio nog; het woord log-odds komt alleen even langs. Eerst de drie rekenstappen. De rest volgt in 4.1.f en verder.
4.1.a Null-model — hoe goed gokt de pad zonder verdere info?
De pad heeft dieren in zijn boekje. Voordat hij naar voorspellers kijkt, vraagt hij: als ik niets weet over een specifiek dier, wat is dan mijn beste gok?
# Dezelfde telling als één zin: neem de data, en vat hem samen. Het pijltje# |> geeft wat links staat door aan wat rechts komt. summarise() perst de# hele tabel samen tot één regel; n() telt de rijen. Een gemiddelde van# WAAR/ONWAAR is het aandeel WAAR, dus mean(... == 1) is de proportie turers.pad_spiegel |>summarise(N =n(),n_tuurt =sum(bekeek_zichzelf ==1),p_tuurt =round(mean(bekeek_zichzelf ==1), 3))
N n_tuurt p_tuurt
1 152 73 0.48
Zo’n model zonder voorspellers heet het null-model. Het geeft elk dier dezelfde kans, wat je verder ook over dat dier weet. Zijn beste gok is dus ook voor elk dier dezelfde: de uitkomst die het vaakst voorkomt. Elk model dat hierna komt, leg je naast dit null-model: brengt wat je over een dier weet de gok dichter bij wat er echt gebeurt?
OpmerkingVraag 4.1.a — Pen-en-papier
a) Hoeveel dieren noteerde de pad in totaal? Hoeveel daarvan tuurden er?
b) Bereken handmatig . Op twee decimalen.
c) De pad ziet een nieuw dier langs lopen. Hij weet niets over dit dier. Wat is zijn beste gok: tuurt of tuurt niet? Met welke kans gokt hij goed?
d) Bij die strategie — altijd hetzelfde gokken voor elk dier — hoeveel keer per dieren zou hij naar schatting fout zitten?
OpgeletAntwoord 4.1.a — open na je eigen poging
a) dieren in totaal, waarvan turen en niet.
b) . Bijna de helft tuurt.
c) Omdat niet-tuurt iets vaker voorkomt dan tuurt ( versus ), is de beste gok zonder verdere info “tuurt niet”. Hij heeft dan kans om goed te zitten. (Anders zou hij omgekeerd goed zitten — niet veel verschil, hier is het null-model bijna een muntje gooien.)
d) Met de “altijd niet-tuurt”-strategie zit hij ongeveer keer per dieren fout. Dat is veel — bijna de helft. De vraag is dus: kan hij beter doen als hij iets over de dieren weet?
4.1.b Een voorspeller toevoegen — aantal_afwijzingen
De pad heeft een hypothese: misschien turen dieren die net afgewezen zijn vaker in het water — om te checken of er iets aan ze mankeert.
Hij bouwt een logistisch model met één voorspeller: aantal_afwijzingen (interval, aantal recente sociale flops).
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.5429478 0.3142876 -1.727551 0.08406876
aantal_afwijzingen 0.1812410 0.1050218 1.725747 0.08439298
Het getal zelf is het effect op de log-odds, en daar heeft bijna niemand gevoel voor. Het teken lees je wel. Een positieve betekent: hoe meer afwijzingen, hoe groter de kans dat een dier tuurt. Een negatieve : hoe meer afwijzingen, hoe kleiner die kans. Hoe gróót het effect van afwijzingen op turen is, lees je straks af aan de odds ratio.
OpmerkingVraag 4.1.b — Pen-en-papier
a) Lees uit de output de intercept en de coëfficiënt voor aantal_afwijzingen. Noteer ze op drie decimalen.
b) Wat is het teken van ? Wat zegt dat teken over de relatie tussen aantal afwijzingen en de kans op turen?
c) Bedenk in één zin of de hypothese van de pad door dit teken bevestigd of weerlegd wordt.
OpgeletAntwoord 4.1.b — open na je eigen poging
a) (intercept), (helling voor aantal_afwijzingen).
b) is positief: hoe meer afwijzingen, hoe groter de kans dat een dier in het water staart.
c) De hypothese van de pad wordt bevestigd door het teken: afgewezen dieren zoeken vaker hun spiegelbeeld op. Of het effect ook significant van nul afwijkt is een vraag voor straks (4.1.f).
4.1.c Van naar kans — de sigmoid-formule
Het teken alleen voorspelt geen concrete kans. Voor “wat is de kans dat een dier met afwijzingen tuurt?” heb je de logistische regressie-vergelijking nodig:
Hier is — Eulers getal, zoals een vaste constante. Op een rekenmachine staat de knop als eˣ of exp; in R is dat exp(). Wat er in de exponent ook uitkomt, groot of klein, positief of negatief: de formule maakt er altijd een kans tussen en van.
TipReken-truc — de gek-ding-vorm
Voor snelheid op je rekenmachine: noem de exponent-uitdrukking even (hoofdletter; let op — niet hetzelfde als , kleine letter):
Eerst reken je uit (één keer typen). Dan gek-ding gedeeld door plus gek-ding. Klaar.
In R kun je het ook automatisch via predict():
# Bereken kansen voor een paar X-waarden via R:nieuw <-data.frame(aantal_afwijzingen =c(0, 2, 3, 5))nieuw$P_tuurt <-predict(m_afw, newdata = nieuw, type ="response")round(nieuw, 3)
a) Reken handmatig voor een dier met . Toon ook tussenstap .
b) Idem voor . Wat valt je op aan de uitkomst?
c) Idem voor .
d) Zonder uit te rekenen: bij welke -waarde ligt precies op ? (Hint: gebruik de drempel-truc uit de mini-callout hieronder.)
TipDe drempel-truc — bij welk is ?
Met het gek-ding van hierboven: is precies als , want . En is precies als de exponent nul is. Dus: zet , los op naar :
Voor ons: . Bij precies afwijzingen kantelt het model van “voorspelt niet-tuurt” naar “voorspelt tuurt”.
OpgeletAntwoord 4.1.c — open na je eigen poging
a) . Dan . Een dier zonder afwijzingen heeft ~ kans om te turen.
b) . Dan . Bij precies afwijzingen voorspelt het model fifty-fifty. Dat is het kantelpunt.
c) . Dan . Een dier met afwijzingen heeft ~ kans om te turen.
d) Bij afwijzingen. Klopt met antwoord (b).
Inzicht. Het model maakt van aantal_afwijzingen een continue kans tussen en . Bij weinig afwijzingen voorspelt het “niet-tuurt”, bij veel afwijzingen “tuurt”, en bij precies afwijzingen weet het model het niet — die waarde is de drempel.
4.1.d Odds — een eerste laag ratio
Een odds is een verhouding: hoe vaak verwachten we ten opzichte van ? In formule:
Zie wat hier gebeurt: de odds is al een ratio. Eén dier-situatie, twee kansen tegen elkaar afgezet. Eerste laag: één ratio.
TipEén meeuw — odds is al een ratio
Stel een zilvermeeuw vangt vis bij van zijn duik-pogingen. Op een dag van pogingen:
Eén dag duiken: de vangst van de zilvermeeuw
Vis gevangen
Niet gevangen
Totaal
Zilvermeeuw
70
30
100
Kans op vis:
Kans op niet-vis:
Odds op vis — “voor elke keer dat hij faalt, slaagt hij keer” of “ op ”
Eén meeuw, twee mogelijkheden, één verhouding. Eerste laag.
Odds en kans zeggen hetzelfde, op twee schalen. Een kans van is odds : even vaak wel als niet. Een kans boven geeft odds boven , een kans onder odds onder . Alleen de bereiken verschillen: een kans zit opgesloten tussen en , odds lopen van tot oneindig.
Voor onze pad — terug naar aantal_afwijzingen. Uit de kansen die je in 4.1.c hebt uitgerekend, volgen direct de odds:
# mutate() zet er een kolom bij en geeft de hele tabel terug. Vandaar de# toewijzing nieuw <- ervoor: zonder die regel reken je het uit en gooi je# het meteen weer weg.nieuw <- nieuw |>mutate(odds_tuurt = P_tuurt / (1- P_tuurt))round(nieuw, 3)
Nog één woord voordat je rekent. Wat in de gek-ding-vorm in de exponent stond, , heet de log-odds of logit: de logaritme van de odds. Een raar woord, maar laat je er niet door blokkeren. Denk gewoon: hoe hoger de log-odds, hoe meer kans. Het kantelpunt ligt bij nul: log-odds hoort bij odds en dus bij kans . Negatieve log-odds horen bij een kans onder , positieve bij een kans erboven.
Het gek-ding uit 4.1.c ís dus de odds. Bij nul afwijzingen: , hetzelfde getal als in de odds-kolom hierboven. Terug gaat met de logaritme: . Gebruik daarvoor de knop ln op je rekenmachine, niet log (die rekent met grondtal ). In R en in de formules van dit thema heet hij gewoon , en dan bedoelen we steeds deze natuurlijke logaritme.
OpmerkingVraag 4.1.d — Pen-en-papier
a) Reken uit de kansen die je in 4.1.c hebt gevonden de odds voor elk niveau van aantal_afwijzingen (, , ).
b) Bij aantal_afwijzingen = 3 heb je . Wat zijn de odds dan? Wat valt je op aan dat getal?
c)Snelle weg: omdat de logaritme ongedaan maakt, is . Reken dat uit voor dezelfde drie waarden. Klopt het met je antwoorden bij (a)?
OpgeletAntwoord 4.1.d — open na je eigen poging
a) Met de drie kansen :
odds =
b) Bij is odds . Even waarschijnlijk wel als niet — fifty-fifty in odds-taal heet één-op-één.
c) Snelle weg via de logit: als , dan . Voor : . Voor : . Voor : . Dat zijn dezelfde odds als bij (a), op de derde decimaal na: daar liep de route via de kans, en die was al afgerond ( tegenover ). Rond pas aan het eind af, dan kom je op beide routes op hetzelfde getal uit.
4.1.e Odds ratio — een ratio van ratios
Als odds een ratio is binnen één situatie, dan is de odds ratio (OR) een ratio tussen twee situaties — bv. tussen twee waarden van .
Dat geldt voor elke eenheids-stijging in — de OR is constant. Dat is de essentie van logistische regressie: per eenheid omhoog, vermenigvuldigen de odds met dezelfde factor.
TipTwee meeuwen — odds ratio (een ratio van ratios)
Naast de zilvermeeuw vliegt een stormmeeuw, die in van zijn pogingen vis vangt:
Eén dag duiken: de vangst van twee meeuwen
Vis gevangen
Niet gevangen
Totaal
Zilvermeeuw
70
30
100
Stormmeeuw
40
60
100
Odds zilvermeeuw ← eerste laag ratio
Odds stormmeeuw ← eerste laag ratio
Odds ratio ← tweede laag ratio
“De zilvermeeuw heeft keer hogere odds op vis dan de stormmeeuw.” De OR is letterlijk een ratio van ratios — eerst per dier odds, dan die odds op elkaar gedeeld.
TipOR als factor — de drie ankerwoorden
De OR is een factor: een vermenigvuldigingsgetal waarmee je de odds vermenigvuldigt om bij de nieuwe odds te komen, als je met één eenheid laat toenemen. Drie woorden, één concept.
Factor — als ik “factor tien” tegen jouw leeftijd gooi, en jij bent , dan ben je opeens jaar. Geen plus tien, geen min tien — keer tien. Zo werkt OR. Lineair gedraagt zich additief; exponentieel gedraagt zich multiplicatief. Plus / min versus keer / door.
Het teken van zie je terug in de OR. Bij is : keer één, de odds blijven gelijk, geen effect. Een positieve geeft een OR boven , een negatieve een OR onder . Wil je de OR in procenten zeggen, dan gaat dat over de odds en niet over de kans: maakt de odds hoger, maakt ze lager.
Voor onze pad:
# Odds ratio per extra afwijzing — uit het model:OR <-exp(coef(m_afw)["aantal_afwijzingen"])round(OR, 3)
aantal_afwijzingen
1.199
OpmerkingVraag 4.1.e — Pen-en-papier
a) Reken handmatig uit (op je rekenmachine eˣ of exp).
b) Interpreteer in één zin: wat zegt deze OR over het effect van één extra afwijzing op de kans dat een dier tuurt?
c) Voor vijf extra afwijzingen: bereken . Wat zijn dan de odds van een dier met afwijzingen, ten opzichte van een dier met afwijzingen?
d) Vergelijk je antwoord bij (c) met de odds-tabel uit 4.1.d: klopt de berekening?
OpgeletAntwoord 4.1.e — open na je eigen poging
a) . (R rekent met de onafgeronde en geeft .)
b) Per één extra afwijzing worden de odds dat het dier tuurt vermenigvuldigd met factor — een toename van ongeveer in de odds. (Niet in de kans direct! De kans schaalt niet-lineair met de odds.)
c) . De odds van een dier met afwijzingen zijn ongeveer keer zo groot als de odds van een dier met afwijzingen.
d) Via de odds-tabel: . Op de derde decimaal na hetzelfde als bij (c): beide routes rekenen met afgeronde tussenstappen. R, zonder iets af te ronden, komt op .
Inzicht. De OR is constant over — dezelfde factor geldt of je van naar gaat, of van naar . Op odds-schaal is logistische regressie lineair-in-de-vermenigvuldiging. Dat is wat in essentie zegt.
Tot hier: drie rekenstappen — kans → odds → odds ratio — met één voorspeller. Hierna komen toets-vragen: wijkt van nul af in de populatie? (Wald-toets, 4.1.f) en doet het model als geheel iets? (LR-toets, 4.1.g). En daarna pas een uitbreiding naar meerdere voorspellers tegelijk.
4.1.f Wald-toets — wijkt in de populatie af van nul?
We hebben in de steekproef gevonden. Maar dat is een schatting. De vraag is: kunnen we ook in de populatie zeggen dat afwijzingen iets te maken hebben met turen? Daarvoor toetsen we de populatie-coëfficiënt tegen nul. De ster () maakt zichtbaar dat het over de populatie gaat en niet over de van deze dieren, net als in thema 1. Een Griekse zie je hier dus niet: die letter is in dit boek het gestandaardiseerde gewicht uit thema 1.
Belangrijk en — populatie-taal, geen significantie
De hypothesen gaan over de populatie, niet over je steekproef en niet over een -waarde:
— in de populatie heeft aantal_afwijzingen geen effect op de log-odds van turen.
— in de populatie heeft aantal_afwijzingen wel een effect op de log-odds van turen.
“De is dat het niet significant is” — die zin klopt nooit. Significantie is een eigenschap van de toetsuitkomst, niet van de coëfficiënt of van de hypothese.
De Wald-toets vergelijkt de steekproef-coëfficiënt met zijn standaardfout . Twee gedaanten, mathematisch identiek:
R’s summary() geeft (geen ). In SPSS-output en in veel rapportages staat . Beide verwijzen naar dezelfde toets — de ene is het kwadraat van de andere — dezelfde -waarde.
# Coëfficiënten met SE en z-waarde:round(summary(m_afw)$coefficients, 3)
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.543 0.314 -1.728 0.084
aantal_afwijzingen 0.181 0.105 1.726 0.084
OpmerkingVraag 4.1.f — Pen-en-papier
Met en :
a) Bereken Wald- handmatig.
b) Bereken .
c) De -waarde uit de output is . Verwerp je op ?
d) Welke conclusie trek je over de populatie? Formuleer in één zin volgens de regels uit de -callout hierboven.
e) De pad’s hypothese was dat afgewezen dieren vaker turen. Heeft de Wald-toets die hypothese ondersteund?
OpgeletAntwoord 4.1.f — open na je eigen poging
a) . (Klein-positief — wijst dezelfde kant op als , maar niet zwaar.) De uitvoer van R zegt , omdat R met de onafgeronde en rekent.
b) . (Mathematisch identiek aan de -toets — zelfde toets, andere vorm.) Rond pas aan het eind af: wie eerst afrondt op , komt op . En R zelf, met zijn onafgeronde , komt op : dat getal zie je in SPSS-uitvoer staan.
c) . We verwerpen niet. Op kunnen we niet concluderen dat in de populatie.
d)In de huidige steekproef () is het effect van aantal_afwijzingen op de log-odds van turen niet groot genoeg om met voldoende zekerheid te zeggen dat in de populatie van nul afwijkt. Korter, niet-significant betekent niet “geen effect” — het betekent “niet genoeg signaal in deze data om te concluderen dat het effect bestaat”.
e) Strikt genomen: de Wald-toets geeft onvoldoende bewijs om de hypothese te ondersteunen. Maar het teken van is wel positief, en de -waarde zit dichtbij — er zit iets in de data dat de hypothese-richting wijst. Mogelijk wordt het effect van afwijzingen op de log-odds van turen wel significant als we andere voorspellers toevoegen (in het volle model hierna komt aantal_afwijzingen als deel van een groter model wel uit met ). Een voorspeller alleen vertelt zelden het hele verhaal.
Inzicht. De Wald-toets ( of ) zegt iets over één specifieke coëfficiënt in het model dat je nu hebt gefit. Bij een enkel-voorspeller-model zit veel ruis nog in de residuen — het model verklaart maar een klein stukje. In het volle model hierna breiden we uit met leeftijd en diersoort, en dan komt het beeld scherper.
4.1.g Likelihood-ratio-toets — doet het model als geheel iets?
De Wald-toets kijkt per coëfficiënt. De likelihood-ratio-toets (LR) kijkt naar het model als geheel: brengt onze voorspeller aantal_afwijzingen de voorspellingen dichter bij de echte data dan een model zonder voorspellers (het null-model)?
TipVerhaalfiguur — drie steden, drie modellen, één lijn
Stel je drie steden voor op een rechte lijn: Leiden, Voorhout, Haarlem. En ergens voorbij Haarlem ligt de data — de werkelijkheid.
Stad
Model
Wat het doet
Leiden
— null-model
gokt als één algemeen gemiddelde. Geen voorspellers.
Voorhout
— model met één voorspeller
bv. alleen aantal_afwijzingen. Iets dichter bij data.
Haarlem
— volledig model
alle voorspellers (komt straks, in het volle model). Het dichtst bij data.
De deviance () is de afstand van dat model tot de data. Hoe groter, hoe verder weg. Het null-model in Leiden ligt het verst. Voeg een goede voorspeller toe, en je schuift op naar Voorhout. Een volledig model brengt je naar Haarlem.
De LR-toets vraagt: hoeveel kilometer zijn we opgeschoten door deze voorspeller toe te voegen — en is dat opvallend meer dan we van een willekeurige uitbreiding zouden verwachten?
Concreet voor onze pad:
# Null-model — alleen intercept (= Leiden):m_nul <-glm(bekeek_zichzelf ~1,data = pad_spiegel,family =binomial(link ="logit"))# LR-toets: model met aantal_afwijzingen versus model zonder:anova(m_nul, m_afw, test ="Chisq")
WaarschuwingDrie namen voor één ding — deviance, , residual deviance
In formules, R-output en handboeken kom je drie verschillende termen tegen die naar hetzelfde getal verwijzen:
Hoe genoemd
Waar je het ziet
(of )
Formules, SPSS-uitvoer
Deviance
Handboeken, artikelen
Residual deviance
R-output van summary(glm(...))
staat voor log-likelihood: hoe aannemelijk de data zijn onder het model. Keer maakt er een positief getal van dat je als afstand leest. Hoe kleiner, hoe dichter bij de data. Voor onze pad:
Null deviance: 210.48 on 151 degrees of freedom
Residual deviance: 207.40 on 150 degrees of freedom
— de afstand-verbetering van Leiden naar Voorhout.
Let op in de uitvoer van anova() hierboven: daar staan de twee afstanden in de kolom Resid. Dev. De kolom die Deviance heet, is hun verschil, de zelf.
OpmerkingVraag 4.1.g — Pen-en-papier
a) Lees uit de R-output (of het kader Drie namen voor één ding hierboven) de twee deviances: null en residual.
b) Bereken handmatig.
c) Hoeveel vrijheidsgraden heeft de LR-toets hier? (Hint: = aantal toegevoegde voorspellers.)
d) Uit de R-output is . Verwerp je op ?
e) Vergelijk je met de Wald- uit 4.1.f. Geven beide toetsen dezelfde conclusie? Wat valt je op aan het kleine verschil in getallen?
OpgeletAntwoord 4.1.g — open na je eigen poging
a) Null deviance ; residual deviance van het model met aantal_afwijzingen .
b) — let op: gebruik onafgeronde getallen anders klopt de aftrekking niet (de sudoku-eigenschap; die komt terug bij de modelvergelijking in het volle model).
c) — we voegen één voorspeller toe (aantal_afwijzingen).
d) . We verwerpen niet. De LR-toets ondersteunt op niet de hypothese dat het model significant beter is dan het null-model.
e) Beide toetsen geven — dezelfde conclusie (niet-significant). Wald- versus LR- verschillen marginaal. Bij grote en simpele modellen geven Wald en LR vrijwel dezelfde uitkomst. Het kleine verschil komt doordat ze via andere formules tot een toets-statistiek komen — Wald via , LR via deviance-aftrekken. In ons geval levert dat zo’n tiende verschil op. Verwaarloosbaar voor de conclusie.
Inzicht. Wald en LR doen op model-niveau vrijwel hetzelfde werk. Het verschil wordt merkbaar bij (1) factoren met meerdere niveaus — daar bundelt LR alle dummies in één toets, terwijl Wald per dummy een aparte toets levert; en (2) kleine steekproeven of heel grote effecten — daar kunnen de twee uiteenlopen. Vuistregel: bij twijfel, en altijd voor factoren als geheel, LR.
We hebben nu de drie rekenstappen (kans → odds → OR) én de twee toetsen (Wald, LR) op één voorspeller doorlopen. Het effect van aantal_afwijzingen alleen blijkt marginaal niet-significant (). Dat is niet “geen effect” — dat is “in deze data niet sterk genoeg om met zekerheid te concluderen, gegeven alleen deze ene voorspeller”. Hierna breidt het model zich uit naar leeftijd en diersoort — en daar komt het beeld scherper uit.
4.2 Het volle model — meerdere voorspellers tegelijk
Tellen wat voorbij komt — en wat voorbij gaat
“Eén bit per dier,” zei de pad. “Maar als ik weet bij welke combinatie het spiegelen wél gebeurt, weet ik morgen wie er nieuwsgierig naar zijn eigen smoeltje zal zijn.”
OpmerkingVoor je gaat rekenen — vijf vragen aan jezelf
Het stappenplan dat in elk thema terugkomt, met de techniek-keuze als laatste stap.
Wie of wat wordt er gemeten?De pad heeft dieren genoteerd.
Wat wordt er gemeten?Vier variabelen per dier: bekeek_zichzelf, leeftijd, aantal_afwijzingen, diersoort.
Onafhankelijk of afhankelijk?Onderzoeksvraag: voorspellen leeftijd, aantal afwijzingen en diersoort of een dier zichzelf bekijkt? Dan is bekeek_zichzelf afhankelijk (), de andere drie onafhankelijk ().
Meetniveau van elke variabele?bekeek_zichzelf binair, leeftijd interval, aantal_afwijzingen interval, diersoort nominaal (3 niveaus).
Welke techniek? Doorloop de beslisboom:
flowchart TD
A[Hoeveel afhankelijke<br/>variabelen?] -->|één| B[Y meetniveau?]
A -->|meerdere| Z[MANOVA<br/><i>thema 5</i>]
B -->|interval| C[X-en meetniveau?]
B -->|binair| D[Logistic regression<br/><i>dit thema</i>]
C -->|alleen interval| E[Multiple regression<br/><i>thema 1</i>]
C -->|alleen nominaal| F[ANOVA<br/><i>thema 2</i>]
C -->|gemengd| G[ANCOVA<br/><i>thema 3</i>]
style D fill:#faf3e2,stroke:#c9a05a,stroke-width:2px
OpmerkingPijltjes-overzicht — alle MVDA-technieken in één tabel
Dezelfde keuze, anders genoteerd. Lees als predictor(en) (meetniveau) → DV(s) (meetniveau):
#
Predictor(en)
DV(s)
Techniek
dich |X|
|Y| int
-toets
nom 3+lvl |X|
|Y| int
éénweg ANOVA
1
int |X X …|
|Y| int
MRA — thema 1
2
nom |X X|
|Y| int
factorial ANOVA — thema 2
3
nom + int |X C|
|Y| int
ANCOVA — thema 3
4
bo(in) |X|
|Y| bin
LRA — thema 4
5
nom |X|
|Y₁ Y₂ …| int
MANOVA — thema 5
6
within-subject momenten
|Y₁ Y₂ Y₃ Y₄| int
RMA — thema 6
7
indirect via
pad
Mediation — thema 7
is binair (bekeek_zichzelf), -en zijn gemengd. Meetniveau van doet er minder toe — wat de techniek bepaalt is de aard van . Antwoord: logistic regression.
T1 — Techniek-keuze: LRA, MRA, ANOVA of ANCOVA?
OpmerkingVraag T1 — Pen-en-papier
Voor elk vignet: bepaal afhankelijke variabele, meetniveau van elke voorspeller, en kies dan de techniek.
a)Een vleermuis registreert per nachtelijke vlucht of hij prooi heeft gevangen (ja/nee), met de continue voorspellers maan-helderheid en jachtduur.
b)Een psycholoog meet bij studenten hun studie-uren-per-week als functie van slaapkwaliteit en zelf-gerapporteerde motivatie — beide continu.
c)Een sportcoach vergelijkt drie trainingsregimes (traag opbouwend / interval / krachtgericht) op rondetijd (). Bij lopers.
d)Een kerkuil meet per nest of een kuiken het overleeft (ja/nee), met als voorspellers nesthabitat (drie typen) en gewicht-bij-uitkomst (continu).
OpgeletAntwoord T1 — open na je eigen poging
a) = prooi-gevangen (BIN), twee continue -en. LRA.
b) = studie-uren (interval), twee continue -en. multiple regressie-analyse (thema 1).
c) = rondetijd (interval), één factor (trainingsregime, NOM, 3 niveaus). eenweg-ANOVA (thema 2).
d) = overleeft (BIN), één factor (nesthabitat) + één continue covariaat (gewicht). LRA. Niet ANCOVA: ANCOVA vereist een continue . Bij binaire wordt het altijd LRA, ongeacht de mix van -meetniveaus.
Vuistregel. Het meetniveau van bepaalt de techniek-familie. Binaire LRA. Continu + alleen continue MRA. Continu + alleen factor(en) ANOVA. Continu + factor + covariaat ANCOVA.
T2 — Odds versus probability
OpmerkingVraag T2 — Pen-en-papier
Odds en kansen zijn twee manieren om hetzelfde feit te beschrijven, maar op verschillende schalen.
a) Bij een kans : wat is de odds? En de log-odds (logit)?
b) Bij : wat is de odds? En de log-odds?
c) Stel je leest af dat de odds van slagen voor een tentamen . Wat is de bijbehorende kans ?
d) Bij negatieve log-odds is de kans… groter of kleiner dan ?
OpgeletAntwoord T2 — open na je eigen poging
a) Odds = . Log-odds = .
b) Odds = . Log-odds = .
c) .
d) Kleiner dan . Bij geldt ; bij geldt ; bij geldt .
4.2.a Verkenning — frequenties en wolken
Voordat de pad fit, kijkt hij eerst.
Algemene vorm.
table(mijn_data$Y)prop.table(table(mijn_data$Y))table(mijn_data$factor, mijn_data$Y)# Continue X tegenover Y — boxplot per uitkomst-categorie.boxplot(X1 ~ Y, data = mijn_data)
# Kruistabel: tel per combinatie, en zet de uitkomst daarna in twee kolommen# naast elkaar (pivot_wider, uit tidyr), zodat hij leest als table().pad_spiegel |>count(diersoort, bekeek_zichzelf) |>pivot_wider(names_from = bekeek_zichzelf, values_from = n)
# A tibble: 3 × 3
diersoort `0` `1`
<fct> <int> <int>
1 ree 40 24
2 vos 9 46
3 das 30 3
a) Hoeveel dieren heeft de pad genoteerd? Welke proportie bekeek zichzelf?
b) Hoe verschilt de mediane leeftijd tussen “wel bekeken” en “niet bekeken”? In welke richting?
c) Idem voor aantal afwijzingen.
d) Lijkt diersoort uit te maken? Welke richting?
OpgeletAntwoord 4.2 — open na je eigen poging
In gewone woorden.
, waarvan zelf-bekijkers () en niet-bekijkers () — vrijwel balanced ().
Op de boxplot ligt de mediane leeftijd bij bekijkers lager dan bij niet-bekijkers — jonger geeft meer spiegel-gedrag.
De afwijzingen-boxplot wijst de andere kant op: bij bekijkers liggen de aantallen afwijzingen iets hoger — wie afgewezen wordt, zoekt het water op om eens goed te kijken wie er voor schut staat.
De kruistabel laat zien dat vossen relatief vaak in de “wel bekeken”-cel zitten ( van vossen), dassen bijna nooit ( van ), reeën wisselend ( van ). Vossen zijn de narcisten van het bos.
APA-stijl.
Van dieren bekeken () zichzelf in het water. Beschrijvend lag de mediane leeftijd bij bekijkers lager dan bij niet-bekijkers, lag het aantal afwijzingen bij bekijkers iets hoger, en kwam zelfreflectie veel vaker voor bij vossen dan bij dassen.
4.2.b Het volle model fitten — alle voorspellers tegelijk
De familie binomial(link = "logit") zegt: “ is binair, en model dit op de log-odds-schaal.” glm() schat de coëfficiënten op een andere manier dan lm() bij MRA (met maximum likelihood in plaats van met kleinste kwadraten). Wat je daarvan in de uitvoer merkt: per coëfficiënt een -toets in plaats van een -toets.
BelangrijkWald- in summary() versus Wald- in rapportage
summary() toont per coëfficiënt de Wald-:
Maar in rapportage (zoals in SPSS-output en in veel APA-stijl-papers) staat meestal de Wald- — dezelfde toets, andere vorm:
Mathematisch identiek. Een wordt — exact dezelfde -waarde. De ene is gewoon het kwadraat van de andere. De omdat we één coëfficiënt toetsen.
Lees-conventie:
Uit summary() lees je z value en Pr(>|z|).
In rapportage schrijf je , — kwadrateer de .
Bij twijfel: noteer beide, bijvoorbeeld “, equivalent , p = .012”.
Call:
glm(formula = bekeek_zichzelf ~ leeftijd + aantal_afwijzingen +
diersoort, family = binomial(link = "logit"), data = pad_spiegel)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.43231 0.58160 -0.743 0.4573
leeftijd -0.14707 0.06703 -2.194 0.0282 *
aantal_afwijzingen 0.29008 0.13499 2.149 0.0316 *
diersoortvos 2.35041 0.47589 4.939 0.000000785 ***
diersoortdas -1.74150 0.67515 -2.579 0.0099 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 210.48 on 151 degrees of freedom
Residual deviance: 144.26 on 147 degrees of freedom
AIC: 154.26
Number of Fisher Scoring iterations: 5
OpmerkingCategorische voorspellers met meer dan twee niveaus
diersoort is een factor met drie niveaus (ree, vos, das). Wat doet R daarmee in glm()?
R maakt automatisch dummy-variabelen (treatment-coding): voor niveaus krijg je dummies, één per niet-referentieniveau.
De referentiecategorie is het eerste level van de factor (hier: ree). R gebruikt levels(factor)[1] als referentie. Bij factor() zonder expliciet levels=-argument is dat alfabetisch eerste; in onze data wordt de level-volgorde expliciet gezet (ree, vos, das). Wijzigen kan via pad_spiegel$diersoort <- relevel(pad_spiegel$diersoort, ref = "vos").
In summary() zie je per niet-referentieniveau één coëfficiënt + Wald-toets — dat is een vergelijking met de referentie, niet een toets op het niveau zelf.
Eén OR per dummy = factor waarmee de odds vermenigvuldigen vergeleken met de referentie.
Voor de vraag “is de factor als geheel voorspellend?” gebruik je anova(model_zonder, model_met, test = "Chisq") (LR-toets) of car::Anova(model, type = "II", test.statistic = "LR"). Dat bundelt alle dummies in één -toets met .
Mini-oefening. Maak een kopie van de data met vos als referentiecategorie (pad_vos <- pad_spiegel; pad_vos$diersoort <- relevel(pad_vos$diersoort, ref = "vos")) en fit het model opnieuw op pad_vos; zo blijft pad_spiegel zelf zoals hij was, en gaan de vragen hieronder nog over hetzelfde model — om te zien hoe Wald-toetsen veranderen ten opzichte van de huidige ree-referentie. Hoe verandert de OR voor ree? En voor das? Wat blijft hetzelfde aan de output van car::Anova(., test = "LR")? Inzicht: dummies + Wald-toetsen veranderen, de LR-toets op de hele factor niet — die is referentie-onafhankelijk.
OpmerkingVragen 4.2 — volle model (e–g)
e) Welke voorspellers zijn significant volgens de Wald-toets ()?
f) Wat is de geschatte log-odds-coëfficiënt voor leeftijd? Voor aantal_afwijzingen? Wat zegt het teken? (Het getal zelf lees je niet als effect, zijn teken wel.)
g) Wat doet diersoortvos ten opzichte van diersoortree (de referentie)? En diersoortdas?
OpgeletAntwoord 4.2 — open na je eigen poging
In gewone woorden.
Significant (p < .05): leeftijd (summary(): , equivalent , p = .028), aantal_afwijzingen ( / , p = .032), de dummy diersoortvos ( / , p < .001) en diersoortdas ( / , p = .010). Alle vier de effecten staan vlaggetjes.
Leeftijd — negatief teken: jonger geeft meer spiegel-gedrag, een puberale narcisten-trek. Aantal_afwijzingen — positief teken: wie afgewezen wordt, zoekt het water op.
diersoortvos-coëfficiënt — positief, dus vossen bekijken zichzelf veel vaker dan reeën (de referentie). diersoortdas — sterk negatief, dassen tonen weinig zelfreflectie. De pad zag een tweedeling tussen vos en das: vossen, blijkbaar, hebben iets te bewijzen.
APA-stijl (we komen er straks mooier op terug, in de APA-zin aan het eind van deze sectie).
Een logistische regressie van zelf-bekijken op leeftijd, aantal afwijzingen en diersoort toonde een negatief leeftijdseffect (, p = .028) en een positief afwijzingseffect (, p = .032); vossen onderscheidden zich sterk van reeën (, p < .001).
T3 — uit via
OpmerkingVraag T3 — Pen-en-papier
De odds ratio is . Reken zelf:
a) . Wat is ? Interpreteer.
b) . Wat is (afgerond)? Interpreteer.
c) . Wat is ? Interpreteer.
d) Voor de pad-data: aantal_afwijzingen . Wat is per afwijzing? Hint: .
OpgeletAntwoord T3 — open na je eigen poging
a) . Geen effect: bij één-eenheid stijging in blijven de odds gelijk.
b) . Per één-eenheid stijging in verdubbelen de odds.
c) . Per één-eenheid stijging halveren de odds. Spiegelbeeld van b.
d) . Per extra afwijzing worden de odds van zelfreflectie met factor vermenigvuldigd — een stijging van ruim per afgewezen vibe.
T4 — : meerdere eenheden
OpmerkingVraag T4 — Pen-en-papier
De OR voor één-eenheid stijging is . Voor -eenheden stijging:
Voor de pad-data: per afwijzing.
a) Wat is de OR voor een verschil van afwijzingen?
b) Wat is de OR voor een verschil van afwijzingen?
c) Stel een dier had vorige maand afwijzingen, deze maand extra. Hoeveel keer hoger zijn de odds van zelfreflectie, alle andere voorspellers gelijk?
d) Voor leeftijd: per jaar (negatief teken — jonger geeft meer spiegel-gedrag). Wat is de OR voor jaar verschil?
OpgeletAntwoord T4 — open na je eigen poging
a) . Bij drie afwijzingen meer worden de odds bijna keer zo groot.
b) . Vijf afwijzingen meer maakt de odds ruim keer zo groot — dat lijkt extreem; zo werkt exponentieel rekenen.
c) . De odds zijn bijna verdubbeld na twee extra afwijzingen.
d) . Bij vijf jaar oudere dieren halveren de odds van spiegel-gedrag ongeveer.
Inzicht. Odds rekenen vermenigvuldigend, niet optellend. Per eenheid telt op in log-odds, vermenigvuldigt in odds. Vandaar de exponentiële groei (of krimp) bij meer eenheden.
TipBij welk is ? — de drempel-truc (afleiding in drie stappen)
Dit is de drempel-truc uit 4.1.c nog één keer, nu afgeleid in logit-taal, want hij komt regelmatig terug op tentamens: “voor welke waarde van is de slagings-kans precies 50%?” Dat punt is de natuurlijke drempel van het model — daar slaat het van “voorspelt zakken” naar “voorspelt slagen” om. Komt straks terug bij de classificatie (de cutoff).
Voor een model met één voorspeller, , leid je dat punt zo af:
Stap 1. correspondeert met odds , en odds correspondeert met . Dus de logit-vorm wordt:
Stap 2. Los op naar . Sleep naar de andere kant:
Stap 3. Deel beide kanten door :
Bv. bij een fictief logistic-regressie-model met en : . Bij is . Voor voorspelt het model “zakken”, voor “slagen”.
Voor een model met meerdere voorspellers werkt het ook, maar dan moet je de andere ’s vastzetten op een waarde naar keuze (bv. hun gemiddelde, of een specifiek profiel). De formule blijft dezelfde structuur: zet logit op nul, los op naar .
4.2.c Odds ratios en hun 95%-CI — meerdere voorspellers naast elkaar
Algemene vorm.
exp(coef(mijn_model)) # Odds ratios per coëfficiëntexp(confint(mijn_model)) # 95%-CI op odds-schaal (profile-likelihood)exp(confint.default(mijn_model)) # 95%-CI op odds-schaal (Wald, sneller)
confint.default() geeft het Wald-interval: precies , dezelfde som die je met de hand maakt, en met exp() eromheen het interval van de odds ratio. confint() rekent anders (via de zogeheten profile likelihood) en geeft daardoor net iets andere grenzen; bij grote is het verschil klein. In dit hoofdstuk gebruiken we confint.default().
term_labels <-c("(Intercept)"="Intercept","leeftijd"="Leeftijd (jaren)","aantal_afwijzingen"="Aantal afwijzingen","diersoortvos"="Diersoort: vos vs ree","diersoortdas"="Diersoort: das vs ree")co <-summary(m_pad)$coefficientsci <-confint.default(m_pad)or <-exp(co[, "Estimate"])or_lo <-exp(ci[, 1])or_hi <-exp(ci[, 2])# De getallen worden tekst via de fmt_*-functies van de huisstijl (KAAPA):# twee decimalen, een echt minteken, en een p zonder voorloopnul.or_df <-data.frame(term = term_labels[rownames(co)],b =fmt_b(co[, "Estimate"]),se =fmt_se(co[, "Std. Error"]),z =fmt_t(co[, "z value"]),p =palign(sapply(co[, "Pr(>|z|)"], fmt_p)),OR =fmt_b(or),ci =fmt_ci(or_lo, or_hi),row.names =NULL)or_df |>gt() |>fmt_markdown(columns = p) |># fmt_p() levert "< .001"; zo wordt dat weer "<"cols_align("right", columns =c(b, se, z, p, OR, ci)) |>cols_label(term ="",b =md("*b*"),se =md("*SE*"),z =md("Wald *z*"),p =md("*p*"),OR =md("*OR*"),ci =md("95%-CI voor *OR*") ) |>gt_apa(title ="Wie van de dieren naar zichzelf tuurt in de spiegel: coëfficiënten en odds ratios") |>tab_footnote_apa(paste0("Logistische regressie van zelf in de spiegel kijken (1 = ja) op leeftijd, ","aantal afwijzingen en diersoort (referentie: ree), *N* = ", nobs(m_pad), ". ","*b* = coëfficiënt op log-odds-schaal; *SE* = standaardfout; ","*OR* = odds ratio, exp(*b*); CI = betrouwbaarheidsinterval (Wald)."))
Wie van de dieren naar zichzelf tuurt in de spiegel: coëfficiënten en odds ratios
b
SE
Wald z
p
OR
95%-CI voor OR
Intercept
−0.43
0.58
−0.74
.46
0.65
[0.21, 2.03]
Leeftijd (jaren)
−0.15
0.07
−2.19
.028
0.86
[0.76, 0.98]
Aantal afwijzingen
0.29
0.13
2.15
.032
1.34
[1.03, 1.74]
Diersoort: vos vs ree
2.35
0.48
4.94
< .001
10.49
[4.13, 26.66]
Diersoort: das vs ree
−1.74
0.68
−2.58
.010
0.18
[0.05, 0.66]
Note. Logistische regressie van zelf in de spiegel kijken (1 = ja) op leeftijd, aantal afwijzingen en diersoort (referentie: ree), N = 152. b = coëfficiënt op log-odds-schaal; SE = standaardfout; OR = odds ratio, exp(b); CI = betrouwbaarheidsinterval (Wald).
Met de hand. Voor een -betrouwbaarheidsinterval wandel je vanaf standaardfouten naar links en naar rechts. Dat geeft het interval van ; daarna zet je beide grenzen met om naar de odds ratio. Voor leeftijd, met en uit de uitvoer van summary() in 4.2.b, op drie decimalen:
stapgrootte:
ondergrens van :
bovengrens van :
interval van de OR:
Rond pas aan het eind af; dan kom je uit op wat R ook geeft. Het interval van bevat de niet, dus het interval van de OR bevat de niet: het effect van leeftijd op de log-odds van turen wijkt significant van nul af.
OpmerkingVragen 4.2 — odds ratios (h–j)
h) Wat is de OR voor leeftijd? Voor aantal_afwijzingen? Wat betekent dat in plain Nederlands?
i) Reken het -interval van de OR voor aantal_afwijzingen met de hand uit, zoals hierboven voor leeftijd. Bevatten de intervallen van leeftijd en aantal_afwijzingen de waarde ? Wat zegt dat over significantie?
j) Wat is de OR voor diersoort vos versus ree? Wat betekent een OR boven ?
OpgeletAntwoord 4.2 — open na je eigen poging
In gewone woorden.
— per jaar dat een dier ouder is, worden de odds van zelf-bekijken met factor vermenigvuldigd, oftewel lager per jaar. — per extra afwijzing hogere odds van zelfreflectie.
Met de hand voor aantal_afwijzingen:
stapgrootte:
ondergrens van :
bovengrens van :
interval van de OR:
De OR-tabel geeft, afgerond op twee decimalen, . 95%-CI leeftijd — bevat niet, dus significant. CI aantal_afwijzingen — ook niet , ook significant. Een CI die bevat zou betekenen “geen effect kan niet uitgesloten worden”.
— vossen hebben odds van zelfreflectie die ruim tien keer hoger liggen dan reeën, mooie sterke zelfbevestigings-energie. Een OR boven betekent: deze categorie heeft hogere odds dan de referentie.
APA-stijl.
Per jaar dat een dier ouder is, lagen de odds van zelf-bekijken keer zo hoog (-CI ). Per extra afwijzing waren de odds keer hoger (). Vergeleken met reeën hadden vossen odds van (), terwijl dassen de odds verlaagden tot ().
4.2.d Modelvergelijking — likelihood-ratio-toets bij meerdere voorspellers
Hoe ver is dit model van waar de data zijn?
“Hou eens vast,” zei de pad. “Afstanden. Hoe ver is mijn vijver van Leiden? Een eind. Hoe ver is Leiden van Voorhout? Tien kilometer. Hoe ver is Voorhout van Haarlem? Twintig. Drie steden op één lijn. Dat zijn drie modellen.”
Dit zijn de drie steden uit 4.1.g: Leiden is het null-model, Voorhout het model met één voorspeller, en nu komt Haarlem in zicht, het volle model. De deviance () is nog steeds de afstand tot de data, en de likelihood-ratio-toets vraagt nog steeds hoeveel kilometer je bent opgeschoten.
OpmerkingDe deviances van het volle model
Wat R laat zien (knip uit summary(m_pad)):
Null deviance: 210.48 on 151 degrees of freedom
Residual deviance: 144.26 on 147 degrees of freedom
Null deviance = (afstand van het null-model tot de data)
Residual deviance = (afstand van het volle model tot de data)
= het verschil = — hoeveel kilometer dichterbij data je bent gekomen door voorspellers toe te voegen
In rapportage: schrijf gewoon deviance (of in formule-vorm). Residual deviance is R-jargon, niet APA.
OpmerkingWald versus LR — twee toetsen, één doel
Bij MRA gebruik je -toetsen op coëfficiënten en -toetsen op (sub)modellen. Bij LRA bestaan beide soorten ook:
Wald- per coëfficiënt: vergelijkt met via zijn . Snel, direct uit summary().
Likelihood ratiolikelihood ratio tussen twee geneste modellen: . Theoretisch nauwkeuriger, vooral bij factoren met meerdere niveaus of bij lage . Bij grote geven ze meestal vergelijkbare -waardes.
Voor een factor met niveaus toetst de LR-toets alle dummies tegelijk — één met . Dat lees je niet af uit summary(); daarvoor heb je anova(m_zonder, m_met, test = "Chisq") nodig.
Algemene vorm.
# Volledig model versus null-model — toetst of het model als geheel iets doet.m_null <-glm(Y ~1, data = mijn_data, family =binomial(link ="logit"))anova(m_null, mijn_model, test ="Chisq")# LR-toets per term (model met- vs zonder die term).car::Anova(mijn_model, type ="II", test.statistic ="LR")
Voor onze dieren.
# Null-model (alleen intercept).m_null <-glm(bekeek_zichzelf ~1,data = pad_spiegel,family =binomial(link ="logit"))# LR-toets: doet het volledige model iets, ten opzichte van het null-model?anova(m_null, m_pad, test ="Chisq")
BelangrijkGeneste modellen — twee voorwaarden voor de LR-toets
Vraag eerst: wanneer is een vogeltje lekker genest?
Als hij er niet doorheen pleurt. Het nestje draagt elk takje waar de vogel op landt. Niet helemaal de juiste vergelijking voor de wiskunde — wel een geheugensteuntje waar je altijd om kunt lachen. Onthou dat: genest = draagvermogen.
De LR-toets vergelijkt twee modellen, en . Hij werkt alleen als de modellen genest zijn:
Op dezelfde data gefit (zelfde aantal observaties — anders zijn de likelihoods niet vergelijkbaar).
is een deelverzameling van qua voorspellers (alle voorspellers in zitten ook in , plus nog één of meer).
Twee modellen met overlappende-maar-niet-geneste voorspellers toets je niet met de LR-toets. Bij anova(m_null, m_pad, test = "Chisq") moet R-output óók kloppen qua van het verschil: .
BelangrijkDeviances onafgerond rapporteren — anders breekt de sudoku
De LR-toetsstatistiek is een verschil tussen twee deviances:
Als je in een tabel of paper de twee deviances afzonderlijk rapporteert én daarnaast de , dan moet de aftrekking kloppen. Bv. bij onze pad-data:
De twee deviances van de pad en hun verschil
Model
(null)
210.48
(alle voorspellers)
144.26
66.22
Note. = nulmodel, alleen een intercept; = het model met leeftijd, aantal afwijzingen en diersoort. = log-likelihood. Het verschil is de likelihood-ratio-toets van tegen : (4) = 66.22, p < .001.
Reken zelf: . ✓ Sudoku-eigenschap.
Dit gaat mis als je rondt voordat je aftrekt. Bij onze pad gaat het toevallig goed: afgerond op gehele getallen staat er , en wordt afgerond ook . Maar neem twee andere deviances, en : afgerond staat er , terwijl het echte verschil is en afgerond . Een lezer die de drie getallen ziet en wil controleren krijgt dan een aftrekking die er net naast zit. Voor APA-rapportage in een paper:
Liever: deviances rapporteren op decimalen, ook al staat in jouw R-output meer.
Beter nog: deviances alleen rapporteren als ze relevant zijn voor wat je beweert; vaak is alleen genoeg.
(Uitvoer in een opgave of uitwerking is soms al afgerond; dan kun je de aftrek niet meer precies narekenen. Niet jouw fout, wél een leesmoeilijkheid.)
TipVrijheidsgraden bij LRA
Bij Wald per coëfficiënt en LR-toets per term:
Toets
Wald per coëfficiënt
(normaal verdeeld onder )
LR-toets voor één continue voorspeller
LR-toets voor factor met niveaus
LR-toets volledig vs null-model
(totaal aantal voorspellers in het model)
Hoofdrekenbaar voorbeeld. Drie voorspellers (twee continu, één factor met niveaus) leveren in totaal vrijheidsgraden voor de LR-toets volledig vs null. Voor onze pad: leeftijd () + aantal_afwijzingen () + diersoort () = — dat is precies het in de anova()-output.
OpmerkingVragen 4.2 — modelvergelijking (k–m)
k) Wat is voor het volledige model versus null? Met welk en welke ?
l) Is diersoort als geheel significant volgens de LR-toets? Vergelijk met de Wald-toetsen op de losse dummies.
m) Klopt met de hoofdreken-formule?
OpgeletAntwoord 4.2 — open na je eigen poging
In gewone woorden.
, p < .001 — het volledige model verklaart de uitkomst significant beter dan het null-model.
Diersoort als geheel is sterk significant: , p < .001. De losse Wald-toetsen wijzen dezelfde kant op (vos , das ); bij factoren is de LR-toets toch principieel beter omdat hij beide dummies in één hypothese bundelt — vergelijking blijft referentie-onafhankelijk.
Het volledige model verklaarde de uitkomst significant beter dan het null-model, , p < .001. Bij gecontroleerde toetsing per term waren leeftijd (, p = .025), aantal afwijzingen (, p = .025) en diersoort (, p < .001) elk significant.
T5 — Wald versus LR-toets: wanneer welke?
OpmerkingVraag T5 — Pen-en-papier
De Wald--toets (uit summary()) en de LR--toets (uit anova()) toetsen vaak hetzelfde, maar niet altijd op dezelfde manier.
a) Bij één continue voorspeller met één coëfficiënt: zijn de twee toetsen exact hetzelfde, of ongeveer hetzelfde?
b) Bij een factor met niveaus: hoeveel Wald--waardes zie je in summary()? Hoeveel LR-toetsen?
c) Welke toets is geschikter om “doet deze factor er als geheel toe?” te beantwoorden? Waarom?
OpgeletAntwoord T5 — open na je eigen poging
a) Ongeveer hetzelfde — beide toetsen en zijn asymptotisch equivalent. Bij grote en moderate effecten geven ze vrijwel identieke -waardes; bij kleine of grote wijken ze uiteen.
b) Bij een factor met niveaus: dummies in summary(), dus Wald-’s — elk een afzonderlijke vergelijking met de referentie. Eén LR-toets in Anova(., test = "LR") met — de hele factor-bijdrage tegelijk.
c) De LR-toets. De vraag “doet deze factor er toe?” gaat over de hele factor, niet over één specifieke dummy. De Wald per dummy zou je aparte toetsen geven, met multiple-testing-issues. De LR-toets bundelt ze in één getoetste hypothese.
Inzicht. Wald is comfortabel (komt direct uit summary()); LR is robuuster (vooral bij factoren). In rapportage van LRA: gebruik Wald voor losse continue voorspellers, LR voor factoren als geheel en voor model-vergelijking.
OpmerkingVoor wie verder wil — waarom de Wald-toets bij een heel groot effect kan haperen
Bij een heel sterk effect, en zeker in een kleine steekproef, schat glm() naast een grote ook een grote standaardfout . De verhouding valt dan kleiner uit dan je zou verwachten: een zeer sterk effect van op de log-odds lijkt volgens de Wald-toets ineens minder significant dan volgens de LR-toets. Dat heet het Hauck-Donner-effect. De LR-toets kijkt alleen naar hoeveel de deviance daalt als erbij komt, en heeft er geen last van. Nog een reden om bij twijfel de LR-toets te nemen.
4.2.e Pseudo-
De pseudo- van dit thema, , is het deel van de afstand dat het model wegwerkt:
met de deviance van het null-model en die van jouw model. In de code hieronder staat dezelfde breuk twee keer: één keer met de log-likelihoods zelf (de valt in teller en noemer tegen elkaar weg) en één keer met de deviances.
Twee dingen volgen meteen uit die breuk. ligt altijd tussen en : als jouw model geen stap dichter bij de data komt dan het null-model, als de afstand helemaal verdwijnt (: elk dier perfect voorspeld). En hij komt zelden hoog, lager dan je van de bij MRA gewend bent. Zelfs een model dat de kans van elk dier precies kent, weet niet of juist dít dier vandaag tuurt: wel of niet blijft een gok, en die rest blijft in de deviance staan.
# Pseudo-R^2 van Hosmer en Lemeshow — handberekend.LL_null <-as.numeric(logLik(m_null))LL_full <-as.numeric(logLik(m_pad))pseudoR2 <-1- (LL_full / LL_null)round(pseudoR2, 3)
[1] 0.315
# Equivalent via deviances:1- (m_pad$deviance / m_pad$null.deviance)
[1] 0.3145922
OpmerkingWat het getal betekent
: het volle model haalt ruwweg van de deviance van het null-model weg. Dat is de effectgrootte van het model als geheel: hoeveel dichter bij de data kom je met de voorspellers, vergeleken met alleen het intercept? Je leest dit vaak als “het model verklaart van de variantie”. Strikt genomen is het verklaarde deviance en geen verklaarde variantie zoals bij MRA; welk van de twee woorden je ook gebruikt, het gaat om hetzelfde getal. Is dat veel? Voor bestaat geen vaste grens voor klein of groot. Gebruik het vooral om modellen op dezelfde data met elkaar te vergelijken: het model met de hoogste zit het dichtst bij de data. Het model uit 4.1 met alleen afwijzingen (Voorhout) haalt ; met leeftijd en diersoort erbij (Haarlem) wordt dat .
OpmerkingVoor wie verder wil — wanneer is groot?
Pseudo- is een andere maat dan de van MRA, met een eigen schaal. Een ruwe vuistregel, geen vaste afspraak: vanaf acceptabel, vanaf goed, vanaf sterk. Met valt het model van de pad in de trede sterk.
Twee schalen voor twee maten, dus leg ze niet zomaar naast elkaar. Een is op zijn eigen schaal acceptabel. Een MRA- is volgens Cohen nog klein: zijn grenzen zijn klein , matig , groot .
Deviance-staafgrafiek — visualiseer
Toon code (illustratie deviance-decompositie)
D0 <- m_pad$null.devianceDk <- m_pad$devianceD_uitleg <- D0 - Dkdev_df <-data.frame(bron =factor(c("Verklaard\n(null - residual)", "Residual deviance"),levels =c("Verklaard\n(null - residual)", "Residual deviance")),waarde =c(D_uitleg, Dk))ggplot(dev_df, aes(x = bron, y = waarde, fill = bron)) +geom_col(width =0.55) +geom_text(aes(label =sprintf("%.2f", waarde)),vjust =-0.4, size =3.6) +scale_fill_manual(values =c("#0077BB", "#BBBBBB"), guide ="none") +labs(x =NULL, y ="−2 log-likelihood",title ="Deviance-decompositie",# Twee decimalen: met één (66.2/210.5) komt er .314 uit, niet .315.subtitle =paste0("Pseudo-R² = ", sprintf("%.2f", D_uitleg), "/",sprintf("%.2f", D0), " = ",sub("^0", "", sprintf("%.3f", D_uitleg / D0)))) +scale_y_continuous(expand =expansion(mult =c(0, 0.12))) +theme_minimal(base_size =11)
TipWat het plaatje zegt
De totale null-deviance () wordt verdeeld in een verklaard deel (links: ) en een residueel deel (rechts: ). De pseudo- is de verhouding tussen “verklaard” en “totaal”: . Het is geen variantie-decompositie zoals in MRA, maar het idee is analoog — wat heeft het model toegevoegd ten opzichte van niets weten?
T6 — Pseudo-: interpretatie en grenzen
OpmerkingVraag T6 — Pen-en-papier
a) Wat zijn de minimum- en maximumwaarden van Hosmer-Lemeshow pseudo-?
b) Waarom liggen pseudo--waardes typisch lager dan MRA’s ?
c) Voor welke vergelijking is pseudo- wel zinvol?
OpgeletAntwoord T6 — open na je eigen poging
a) Minimum (het model komt geen stap dichter bij de data dan het null-model), maximum (perfect model: residual deviance ).
b) Bij een binaire blijft er altijd gok over: ook wie de kans van een dier precies kent, weet niet of het dier vandaag tuurt. Die rest blijft in de deviance staan, dus komt de teller van zelden in de buurt van de hele noemer.
c) Twee logistische modellen op dezelfde data, met verschillende voorspeller-sets — bijvoorbeeld een model dat stap voor stap voorspellers erbij krijgt. Hoger = meer verklaard. Voor cross-data-vergelijking is de absolute waarde minder informatief.
Inzicht. Pseudo- is een vergelijkings-maat, geen absolute prestatie-maat. Combineer met inhoudelijke effectgroottes (’s) en classificatie-prestatie.
4.2.f Hiërarchische LRA — het model in blokken opbouwen
Eerst wat een dier is, dan wat het meemaakte
“Afwijzingen alleen zeiden te weinig,” zei de pad. “Maar toen wist ik verder ook niets van de dieren. Wat als ik eerst opschrijf wat ik al weet? Doen de afwijzingen er dán nog toe?”
Je kent het uit thema 1, Hiërarchische regressie-analyse: je bouwt het model op in blokken, in een volgorde die je vooraf kiest, op inhoud. Eerst wat je al weet, dan waar je eigenlijk naar vraagt. Bij elke stap stel je twee vragen: is die toevoeging significant? en hoeveel komt erbij? Bij LRA beantwoord je ze met twee dingen uit dit thema.
Is de toevoeging significant? De likelihood-ratio-toets tussen het model vóór en het model ná het blok, met als het aantal coëfficiënten dat het blok toevoegt. Een voorspeller met één getal (interval of 0/1) kost er één; een factor met drie niveaus kost er twee, één per dummy.
Hoeveel komt erbij? De van elk model, uit zijn twee deviances. Die zet je naast elkaar.
De toetsgrootheid van een blok is het verschil in deviance, dezelfde aftrekking als bij elke LR-toets:
De volgorde. De pad kiest drie blokken, van wat een dier ís naar wat het onlangs meemaakte: eerst diersoort (ree, vos of das), dan leeftijd, en als laatste zijn eigen vermoeden, aantal afwijzingen. Zo vraagt het laatste blok precies wat hij wil weten: voegen afwijzingen iets toe als je soort en leeftijd al kent?
Algemene vorm.
m0 <-glm(Y ~1, data = mijn_data, family =binomial(link ="logit"))m1 <-glm(Y ~ X1, data = mijn_data, family =binomial(link ="logit"))m2 <-glm(Y ~ X1 + X2, data = mijn_data, family =binomial(link ="logit"))m3 <-glm(Y ~ X1 + X2 + X3, data = mijn_data, family =binomial(link ="logit"))# Alle blokken in één tabel; per paar kan ook: anova(m1, m2, test = "Chisq").anova(m0, m1, m2, m3, test ="Chisq")# R2_L van één model, uit zijn twee deviances.(m1$null.deviance - m1$deviance) / m1$null.deviance
Voor onze dieren.
# Vier modellen, elk één blok groter dan het vorige, allemaal op dezelfde# dieren: ze zijn dus genest.m_h0 <-glm(bekeek_zichzelf ~1,data = pad_spiegel, family =binomial(link ="logit"))m_h1 <-glm(bekeek_zichzelf ~ diersoort,data = pad_spiegel, family =binomial(link ="logit"))m_h2 <-glm(bekeek_zichzelf ~ diersoort + leeftijd,data = pad_spiegel, family =binomial(link ="logit"))m_h3 <-glm(bekeek_zichzelf ~ diersoort + leeftijd + aantal_afwijzingen,data = pad_spiegel, family =binomial(link ="logit"))# Per blok de LR-toets: elk model tegen het model op de regel erboven.anova(m_h0, m_h1, m_h2, m_h3, test ="Chisq")
Lees de tabel regel voor regel. Regel 1 is het null-model, elke volgende regel is één blok erbij. Per kolom:
Resid. Df: die heb je hier niet nodig.
Resid. Dev: de deviance van het model ná dat blok.
Df: hoeveel coëfficiënten er bij dat blok bijkwamen. Dat is de van de toets.
Deviance: het verschil met de regel erboven. Dat is de van het blok.
Pr(>Chi): de -waarde van het blok.
Let op de nummers in de kop. R telt vanaf 1, dus daar heet het null-model Model 1. In de tekst heet het null-model model 0, en draagt elk model het nummer van zijn laatste blok: model 1 is alleen diersoort, model 2 diersoort en leeftijd, model 3 alle drie (in de code m_h1 tot en met m_h3).
Met de hand, voor het laatste blok. Model 2 (diersoort en leeftijd) zit op deviance , model 3 (met de afwijzingen erbij) op . Het verschil is . R zegt , omdat R aftrekt met de onafgeronde deviances; dat is precies de val uit het kader Deviances onafgerond rapporteren. Neem daarom de uit de kolom Deviance: , p = .025. En van model 3: .
Kijk nog eens naar die teller, : dat is alle afstand die het model sinds het null-model gewonnen heeft, en dus de kolom Deviance opgeteld (, op een afronding na). Elk blok legt er zijn eigen stuk bij.
Zo loopt op van via naar , en alle drie de toevoegingen zijn significant. Twee dingen om bij te onthouden:
kan alleen stijgen. Een blok erbij maakt de afstand tot de data nooit groter, dus stijgt of blijft gelijk, ook als het blok niets betekent. Of de stijging meer is dan toeval, zegt de -toets van het blok. Vraagt een opgave welk model volgens het beste is, dan is dat het model met de hoogste , ook als het laatste blok niet significant was.
Dezelfde voorspeller, een andere vraag. In het begin van dit thema stond aantal afwijzingen er alleen voor, en voegde hij niet significant iets toe aan het null-model (, p = .079). Als laatste blok wel. Dat is geen tegenspraak, want het zijn twee vragen: wat doen afwijzingen als je verder niets weet, en wat voegen ze toe als je soort en leeftijd al kent?
OpmerkingVragen 4.2 — hiërarchische LRA (n–s)
Gebruik de anova()-uitvoer hierboven.
n) Voorspelt diersoort (blok 1) significant of een dier zichzelf bekijkt? Rapporteer , en . Waarom is hier ?
o) Reken van model 1 (alleen diersoort) met de hand uit, uit twee deviances.
p) Voegt leeftijd (blok 2) significant iets toe bovenop diersoort? Rapporteer , en .
q) Reken van model 2 (diersoort en leeftijd) met de hand uit.
r) Stel dat de pad nog een vierde blok had toegevoegd, de kleur van de vacht (één 0/1-voorspeller), en dat de deviance daarmee nog zakte, met p = .37 voor dat blok. Wat wordt ? Is het vierde blok significant? Welk model is dan volgens het beste?
s) Schrijf de uitkomst van de drie blokken op in APA-stijl.
OpgeletAntwoord 4.2 — open na je eigen poging
In gewone woorden.
Ja: , p < .001. De is omdat diersoort drie niveaus heeft en dus als twee dummies in het model komt (vos en das, elk tegen ree): twee coëfficiënten erbij.
.
Ja: , p = .034.
.
De deviance wordt , dus : hoger dan de van model 3. Het blok zelf is niet significant: , p = .37. Toch is model 4 volgens het beste, want het heeft de hoogste waarde. Dat is de valkuil: stijgt bij elk blok, ook bij een blok dat niets betekent. Of een blok significant iets toevoegt, zegt alleen zijn -toets.
APA-stijl.
In een hiërarchische logistische regressie van zelf-bekijken voorspelde diersoort in de eerste stap of een dier zichzelf bekeek, , p < .001. Leeftijd voegde daar in de tweede stap significant iets aan toe, , p = .034, en aantal afwijzingen in de derde stap eveneens, , p = .025. De van het model steeg daarbij van via naar .
Let op bij het afronden naar twee decimalen. De van model 3 is ; dat wordt . Wie vanuit de al afgeronde verder rondt, komt op . Rond dus af vanuit het getal van R, niet vanuit een getal dat al een keer afgerond is.
# Zet de voorspelde kans en de voorspelde klasse als kolommen naast de echte# uitkomst. if_else() is de dplyr-broer van ifelse().pad_klas <- pad_spiegel |>mutate(phat =predict(m_pad, type ="response"),yhat =if_else(phat >=0.5, 1, 0))# De classificatietabel als lijst van combinaties: echt en voorspeld.pad_klas |>count(observed = bekeek_zichzelf, predicted = yhat)
Twee kanten van dezelfde tabel. De rijen zijn wat er echt gebeurde, de kolommen wat het model voorspelt.
Langs de rijen: sensitiviteit en specificiteit (in de code hierboven sensitivity en specificity). Gegeven dat een dier echt tuurt, hoe vaak zegt het model dat ook?
Langs de kolommen: PPV en NPV. Zet alle dieren waarvan het model zegt “die tuurt” bij elkaar aan de vijver en pak er één uit: hoe groot is de kans dat die ook echt tuurt? Dat is de positief voorspellende waarde (PPV). Bij de pad: van de dieren met de voorspelling tuurt, dus PPV .
De negatief voorspellende waarde (NPV) doet hetzelfde met de kolom tuurt niet: van de , dus NPV .
Is dat goed? Leg het aandeel goed naast de gok zonder model. Het null-model van het begin van dit thema zat bij van de dieren goed, door altijd tuurt niet te zeggen; het volle model komt op . Je ziet die vergelijking ook wel “beter dan toeval (50%)” genoemd worden. Dat is hetzelfde getal zolang de twee uitkomsten even vaak voorkomen. Bij een scheve uitkomst scheelt het veel: zijn van de dieren niet-turers, dan zit je met altijd tuurt niet zeggen bij goed, zonder iets over de dieren te weten.
De grens van is een afspraak, geen wet. Leg je hem lager, dan zegt het model vaker tuurt. Je mist dan minder echte turers (de sensitiviteit stijgt), maar je zegt ook vaker tuurt bij een dier dat niet tuurt (de specificiteit daalt). Hoger leggen werkt andersom. Dit oefenboek houdt de grens op : dan kies je per dier gewoon de uitkomst die het model het waarschijnlijkst vindt.
PPV en NPV hangen ook af van hoe vaak de uitkomst voorkomtbase rate. Sensitiviteit en specificiteit zijn eigenschappen van het model. PPV en NPV niet alleen: is turen zeldzaam, dan zitten er onder de dieren met de voorspelling tuurt naar verhouding veel die het niet doen, en zakt de PPV, ook bij een goed model.
OpmerkingVragen 4.2 — classificatie (t–w)
t) Hoeveel dieren zijn correct geclassificeerd? Welk percentage?
u) Wat is de sensitivity? Wat zegt dat?
v) Wat is de specificity? Wat zegt dat?
w) De cutoff staat op . Waarom is dat een keuze, geen wet?
OpgeletAntwoord 4.2 — open na je eigen poging
In gewone woorden.
Diagonaal: correct uit , accuracy .
Sensitivity : van de daadwerkelijke bekijkers heeft het model er correct herkend ().
Specificity : van de niet-bekijkers er correct als niet-bekijker voorspeld () — het model is iets beter in “die kijkt zichzelf níet” zeggen dan andersom.
De cutoff van is een conventie, niet een wet. Als je sensitivity wilt maximaliseren (bv. een dier dat dringend zelfreflectie nodig heeft niet missen), zet je de cutoff lager. Andersom hoger. ROC-curves vergelijken alle cutoffs tegelijk — zie Wat blijft liggen.
APA-stijl.
Op basis van een cutoff van classificeerde het model van dieren correct (accuracy ). Sensitivity , specificity .
T7 — Classificatie-accuratesse + PPV/NPV
OpmerkingVraag T7 — Pen-en-papier
Naast accuracy, sensitivity en specificity zijn ook PPV en NPV relevant (zie Twee kanten van dezelfde tabel hierboven). Stel je leest:
predicted
observed 0 1
0 60 20
1 15 55
a) Bereken accuracy, sensitivity en specificity.
b) PPV : van degenen voor wie het model voorspelt, welk deel heeft echt ? Bereken.
c) NPV : van degenen voor wie het model voorspelt, welk deel heeft echt ? Bereken.
d) Waarom hangt PPV/NPV af van de base rate (het aandeel met in de populatie)?
OpgeletAntwoord T7 — open na je eigen poging
a) Accuracy = . Sensitivity = . Specificity = .
b) PPV = . Van degenen voor wie het model voorspelt, klopt het bij .
c) NPV = . Van degenen voor wie het model voorspelt, klopt het bij .
d) Sensitivity en specificity zijn eigenschappen van het model — onafhankelijk van hoe vaak in de populatie voorkomt. PPV en NPV daarentegen hangen af van de base rate. In een populatie waar heel zeldzaam is, zal PPV laag zijn — zelfs een goed model zal veel false positives geven, simpelweg omdat er weinig echte positives zijn om voorspeld te worden. Vandaar dat een test-met-hoge-sensitivity in een lage-prevalentie-context (bv. zeldzame ziekte) toch tot veel valse alarmen kan leiden.
4.2.h APA-zin — alles in één
Toon code (de getallen voor de APA-zin ophalen)
# Een paar getallen rechtstreeks ophalen voor de zin hieronder.chi <-anova(m_null, m_pad, test ="Chisq")[2, "Deviance"]df_full <- m_pad$df.null - m_pad$df.residualp_full <-anova(m_null, m_pad, test ="Chisq")[2, "Pr(>Chi)"]cat("LR overall: chi^2(", df_full, ") = ",round(chi, 2), ", p = ", signif(p_full, 3),", pseudo-R^2 = ", round(1- m_pad$deviance/m_pad$null.deviance, 3),sep ="")
LR overall: chi^2(4) = 66.22, p = 0.000000000000143, pseudo-R^2 = 0.315
TipEen nette APA-rapportage
Een logistische regressie van zelf-bekijken op leeftijd, aantal afwijzingen en diersoort verklaarde de uitkomst significant beter dan een null-model, , p < .001, pseudo-. Per jaar dat een dier ouder was, lagen de odds van zelf-bekijken keer zo hoog (-CI , p = .028); per extra afwijzing waren de odds keer hoger (, p = .032). Diersoort droeg sterk bij (, p < .001): vossen hadden odds van ten opzichte van reeën, dassen slechts . Op basis van een cutoff classificeerde het model van de dieren correct (sensitivity , specificity ).
OpmerkingVoor wie verder wil — interactie tussen leeftijd en afwijzingen
“Misschien,” zei de pad. “Misschien dat een afgewezen oud dier net zo hard in het water staart als een afgewezen jong dier. Dan is leeftijd niet meer interessant. Dan is afwijzing alles.”
Een logistisch model kun je net als een gewone regressie uitbreiden met een interactieterm. Een interactie tussen leeftijd en aantal afwijzingen zegt: het effect van leeftijd op de log-odds van turen verandert in grootte of richting met het aantal afwijzingen.
m_int <-glm(bekeek_zichzelf ~ leeftijd * aantal_afwijzingen + diersoort,data = pad_spiegel,family =binomial(link ="logit"))# Vergelijk met het model zonder interactie: voegt de interactie iets toe?anova(m_pad, m_int, test ="Chisq")
Analysis of Deviance Table
Model 1: bekeek_zichzelf ~ leeftijd + aantal_afwijzingen + diersoort
Model 2: bekeek_zichzelf ~ leeftijd * aantal_afwijzingen + diersoort
Resid. Df Resid. Dev Df Deviance Pr(>Chi)
1 147 144.26
2 146 143.95 1 0.31881 0.5723
Wat zegt de output? De LR-toets vergelijkt het model met en zonder de interactieterm: , . Geen bewijs dus dat het effect van leeftijd op de log-odds van turen afhangt van het aantal afwijzingen, of omgekeerd. De pad blijft bij het model zonder interactie.
Was de interactie wél significant geweest, dan rapporteer je het model mét interactie en lees je de losse effecten voorwaardelijk, net als in MRA en ANOVA:
Coëfficiënten: is dan het effect van leeftijd op de log-odds van turen bij nul afwijzingen, en niet meer “het” effect van leeftijd.
Odds ratios van die losse effecten gelden dan ook alleen bij die ene waarde van de andere voorspeller.
Vrijheidsgraden: de interactieterm van twee continue voorspellers kost er één.
Toetsen doe je de interactie met de LR-toets: model met tegen model zonder.
Centreren van de continue voorspellers helpt bij het lezen: de losse effecten gelden dan bij het gemiddelde van de andere voorspeller in plaats van bij nul. Thema 3 legt centreren uit.
4.3 Aannamechecks
“Lopen mijn voorspellers wel mooi op de log-odds-schaal?”
LRA leunt op andere aannames dan MRA: vier aannames, plus genoeg dieren.
Log-odds-lineariteit — continue voorspellers moeten lineair samenhangen met de logit van (zie Log-odds-lineariteit hieronder).
Onafhankelijke observaties — geen geclusterde data, geen herhaalde metingen op hetzelfde dier.
Voorspellers zonder meetfout — meetfouten in vertekenen .
Geen sterke multicollineariteit — de VIF-check (zie Multicollineariteit hieronder).
Plus genoeg dieren per voorspeller: (zie Sample-size hieronder).
Onafhankelijkheid en meetfout check je niet in R: die volgen uit hoe de data verzameld zijn (elk dier één keer geteld, een betrouwbaar meetinstrument). Twee aannames die je van MRA kent, vallen hier juist weg: normaliteit en homoscedasticiteit.
WaarschuwingNormaliteit en homoscedasticiteit hoeven NIET (klassieke trick-question)
Op tentamens komt het terug: “Welke aannames moet je checken bij LRA?” en dan staat in de antwoord-opties iets als “normaal verdeelde residuen” en “gelijke varianties tussen groepen”. Dat zijn de afleiders. Wie reflexmatig de MRA- of ANOVA-aannames opdreunt, valt erin.
Waarom werken die aannames hier niet?
is binair. Een binaire variabele is per definitie binomiaal verdeeld, niet normaal. En de variantie van hangt vast aan de kans dat : . Een geeft variantie ; een geeft variantie . Heteroscedasticiteit is dus geen schending — het is de structuur. Daarom ook geen -toets bij LRA, en daarom ook geen Levene of Shapiro-Wilk.
Tentamen-veiligheid: als je bij een LRA-vraag een aanname-checklist moet opnoemen, bouw hem op uit de vier hierboven, plus , niet uit de MRA-aannames. Wie “normaliteit” of “homoscedasticiteit” in zijn LRA-antwoord opneemt, verliest punten.
4.3.a Log-odds-lineariteit
Let op wát er recht moet lopen: niet de kans, want die volgt altijd een S-curve, maar de log-odds. En de aanname geldt alleen voor continue voorspellers. Een factor als diersoort gaat via dummies, met een eigen coëfficiënt per niveau; daar is geen lijn die recht hoeft te zijn.
Algemene vorm. Je bekijkt het: deel een continue voorspeller op in een paar groepjes (bins), reken per groepje de log-odds van uit, en zet die uit tegen . Liggen de punten ongeveer op een rechte lijn, dan houdt de aanname. Is de samenhang duidelijk krom, dan kun je een kwadratische term toevoegen (I(X^2) in de formule) of de voorspeller in een paar groepen indelen. Dat laatste is eenvoudig, maar gooit informatie weg.
Voor onze dieren.
Toon code (visuele log-odds-check)
# Bin de continue voorspellers en bereken de empirische log-odds per bin.bin_logit_plot <-function(x, y, k =8, xlab =deparse(substitute(x))) { qs <-quantile(x, probs =seq(0, 1, length.out = k +1), na.rm =TRUE)# Maak unieke breaks om bins te garanderen. qs <-unique(qs) bins <-cut(x, breaks = qs, include.lowest =TRUE) agg <-aggregate(y, by =list(bin = bins), FUN = mean)# Bereken bin-midpoint mids <-aggregate(x, by =list(bin = bins), FUN = mean)$x ps <-pmin(pmax(agg$x, 0.01), 0.99) logits <-log(ps / (1- ps))plot(mids, logits,pch =19, col ="#0077BB",xlab = xlab, ylab ="Empirische log-odds",main =paste("Log-odds-lineariteit:", xlab))abline(lm(logits ~ mids), lty =2, col ="#EE7733")}par(mfrow =c(1, 2), mar =c(4, 4, 2.5, 1))bin_logit_plot(pad_spiegel$leeftijd, pad_spiegel$bekeek_zichzelf,k =6, xlab ="Leeftijd")bin_logit_plot(pad_spiegel$aantal_afwijzingen, pad_spiegel$bekeek_zichzelf,k =5, xlab ="Aantal afwijzingen")
Toon code (visuele log-odds-check)
par(mfrow =c(1, 1))
OpmerkingVragen 4.3
a) Lopen de empirische log-odds redelijk lineair met leeftijd?
b) Idem met aantal_afwijzingen — let op het bereik aan de rechterkant.
c) Wat zou je doen als één van de twee duidelijk gekromd is?
OpgeletAntwoord 4.3 — open na je eigen poging
In gewone woorden.
Voor leeftijd lopen de bin-punten redelijk dalend: jongere dieren hogere log-odds, oudere lagere — een rechte daling past goed.
Voor aantal_afwijzingen iets meer wisselvallig — bij hoge afwijzings-bins is de schatting onstabiel doordat er minder dieren zijn, maar de gemiddelde trend is nog stijgend.
Bij duidelijke kromming: opties zijn (1) een kwadratische term toevoegen (I(X^2)); (2) categoriseren in groepen; (3) een niet-lineaire link gebruiken (cubic spline, GAM). Categoriseren is laagdrempelig maar verliest informatie; spline/GAM houdt continuïteit (zie Wat blijft liggen).
APA-stijl.
Visuele inspectie van empirische log-odds tegen de continue voorspellers ondersteunde de aanname van log-odds-lineariteit; afwijkingen waren beperkt tot bins met weinig dieren.
OpmerkingVoor wie verder wil — de aanname toetsen in plaats van bekijken
Naast het plaatje bestaat er een toets, de Box-Tidwell-check: zet per continue voorspeller een extra term in het model. Is die term significant, dan buigt de samenhang tussen en de log-odds af van een rechte lijn.
Hij werkt alleen voor een met uitsluitend positieve waarden, want bestaat niet. Bij de pad kan het dus niet zomaar voor aantal_afwijzingen: daar komen dieren met nul afwijzingen in voor.
4.3.b Multicollineariteit — vif()
Dezelfde check als bij MRA: een VIF boven de betekent dat een voorspeller te sterk samenhangt met de andere voorspellers. Alleen ziet de uitvoer er hier anders uit. Omdat diersoort een factor is, geeft vif() geen rijtje getallen maar een tabel met drie kolommen. Lees de eerste, GVIF (de gegeneraliseerde VIF). Voor een voorspeller met één vrijheidsgraad (Df is ), zoals leeftijd en aantal_afwijzingen, is dat gewoon de VIF. Ligt alles in die kolom onder de , dan ben je klaar, ook voor de factor.
d) Wat zijn de VIF’s? Liggen ze onder de grens van ?
OpgeletAntwoord 4.3 — open na je eigen poging
In gewone woorden.
Leeftijd en aantal_afwijzingen hebben elk één vrijheidsgraad, dus hun getal in de eerste kolom ís de VIF: en . Diersoort komt op . Alles ligt rond de , ruim onder de grens van . Geen multicollineariteit-zorg.
APA-stijl.
Multicollineariteit was geen probleem: de VIF’s van leeftijd en aantal afwijzingen waren en , de gegeneraliseerde VIF van diersoort , alle ruim onder .
OpmerkingVoor wie verder wil — de GVIF bij een factor
Voor een factor rekent R een gegeneraliseerde VIF (GVIF) uit over alle dummies samen; de kolom Df zegt over hoeveel dummies. Ligt die GVIF onder de , dan is er niets aan de hand. Komt hij erboven, dan is dat bij een factor nog geen alarm: een GVIF groeit mee met het aantal dummies. Kijk dan naar de derde kolom, . Die is te vergelijken met de wortel uit een gewone VIF, dus de grens van wordt daar . Bij de pad komt die kolom niet boven de .
4.3.c Sample-size — Pedhazur’s
N_obs <-nrow(pad_spiegel)k_terms <-length(coef(m_pad)) -1# exclusief interceptratio <- N_obs / k_termsround(c(N = N_obs, k = k_terms, ratio = ratio), 2)
N k ratio
152 4 38
TipPedhazur’s drempel — strenger dan MRA
Bij MRA hanteren we vaak als sample-size-vuistregel. Voor LRA is de aanbeveling strenger: (Pedhazur, 1997). Reden: een binaire bevat minder informatie per observatie dan een continue .
Wat telt als ? Het aantal coëfficiënten naast het intercept. Een factor telt dus voor zijn aantal dummies: diersoort heeft niveaus en dus dummies. Voor de pad is dat , voor drie voorspellers. In veel opgaven heeft elke voorspeller één coëfficiënt (hij is interval of 0/1); dan zijn de twee tellingen hetzelfde, en tel je gewoon de voorspellers. Zit er toch een factor met meer dan twee niveaus in, tel dan zijn dummies.
Voor onze pad: — boven Pedhazur’s drempel.
Haal je de drempel niet, dan zijn er twee nette uitwegen: minder voorspellers (de inhoudelijk belangrijkste) of meer data.
OpmerkingVoor wie verder wil — tellen in uitkomsten in plaats van in dieren
Een tweede vuistregel kijkt niet naar het totale aantal waarnemingen, maar naar de kleinste van de twee uitkomstgroepen: het aantal events per voorspellerEPV, met meestal als ondergrens. Bij een scheve uitkomst is dat strenger dan . Neem dieren waarvan er maar turen, en voorspellers: , ruim boven de , maar EPV , ver onder de . De schattingen worden dan wankel en de standaardfouten groot. Bij de pad is de kleinste groep dieren, dus EPV .
Voor modellen met veel voorspellers en weinig uitkomsten bestaat naast minder voorspellers of meer data nog een derde weg: penalized regression, zoals de lasso, die de gewichten bewust kleiner schat.
OpmerkingVoor wie verder wil — invloedrijke dieren opsporen met Cook’s distance
Net als bij MRA kun je per dier uitrekenen hoeveel het model verschuift als je dat ene dier weglaat: Cook’s distance.
plot(m_pad, which =4, sub.caption ="",caption ="Cook's distance per observatie")
De hoogste waarde bij de pad is . Een gangbare grens voor “kijk hier eens naar” is ; daar komt geen enkel dier in de buurt. Zie je wel een twijfelgeval, laat het dan niet stilletjes weg: draai het model met en zonder dat dier, en meld of de conclusies veranderen.
T8 — Log-odds-lineariteit: wat is het, hoe checken?
OpmerkingVraag T8 — Pen-en-papier
a) Wat zegt de aanname van log-odds-lineariteit precies? Voor welk type voorspeller geldt hij?
b) Hoe check je hem?
c) Stel je vindt dat een continue voorspeller niet-lineair samenhangt met de log-odds — een U-vormige relatie. Welke aanpassing aan het model zou dat oplossen?
OpgeletAntwoord T8 — open na je eigen poging
a) De relatie tussen elke continue voorspeller en de logit van moet lineair zijn: . Voor factoren geldt de aanname niet — dummies coderen automatisch elk niveau apart, dus geen lineariteit nodig. Alleen continue voorspellers.
b)Visueel: deel op in groepjes, bereken per groepje de empirische logit, zet die uit tegen en kijk of het ongeveer een rechte lijn is.
c) Voeg een kwadratische term toe: Of categoriseer in groepen. Of gebruik een spline/GAM (zie Wat blijft liggen).
T9 — : vergelijken met MRA
OpmerkingVraag T9 — Pen-en-papier
a) Bij MRA hanteert het oefenboek ; bij LRA . Waarom is de LRA-drempel strenger?
b) Een onderzoeker heeft en wil voorspellers in een logistisch model stoppen. . Voldoet dit aan Pedhazur’s vuistregel?
c) Wat is een gangbare oplossing als je sample-size te klein is voor de gewenste voorspeller-set?
OpgeletAntwoord T9 — open na je eigen poging
a) Een binaire bevat per observatie maar één bit informatie. Een continue veel meer (zo veel bits als de meetschaal toelaat). De maximum-likelihood-schatter heeft dus meer observaties nodig om dezelfde precisie te bereiken voor logistische coëfficiënten als OLS voor MRA-coëfficiënten.
b) Nee — Pedhazur’s drempel is per voorspeller, hier zou je willen hebben voor voorspellers.
c) Verminder het aantal voorspellers: kies de inhoudelijk belangrijkste. Of verzamel meer data.
Inzicht. Sample-size-vuistregels zijn vuistregels, geen wetten. Ze zeggen wanneer je schattingen wankel worden, niet wanneer ze ineens fout zijn.
T10 — Niet-significante voorspeller weglaten?
Een voorspeller die niet significant is, haal je niet zomaar uit het model. Drie dingen om te weten voordat je schrapt:
De dummies van een factor horen bij elkaar. Haal je één dummy weg, dan voeg je dat niveau stilletjes samen met de referentie. Een factor laat je dus heel staan of je haalt hem heel weg. Of hij als geheel iets doet, zegt de LR-toets op de hele factor.
Niet significant is niet hetzelfde als onbelangrijk. Hangt een voorspeller sterk samen met een andere voorspeller in het model, dan kan zijn eigen toets niet significant uitvallen terwijl hij samen met die ander wel iets bijdraagt. Kijk eerst naar de VIF’s.
Kiezen op de -waarde, achteraf, maakt vals alarm waarschijnlijker. Wie voorspellers weglaat of toevoegt tot het mooi uitkomt, met de hand of met een automatische stapsgewijze procedure, vindt vaker een effect dat er in de populatie niet is. Kies je voorspellers vooraf, op inhoud, en meld wat je allemaal geprobeerd hebt. Wil je weten wat één voorspeller toevoegt bovenop de rest, zet hem dan als laatste blok in een hiërarchische LRA.
OpmerkingVraag T10 — Pen-en-papier
Stel: in een uitgebreidere versie van de pad-data is een vierde voorspeller seizoen (factor: lente/zomer/herfst/winter) toegevoegd, en blijkt seizoenherfst niet significant () terwijl andere niveaus van seizoen dat wel zijn.
a) Mag je die ene dummy weglaten uit het model? Wat zou er met het model gebeuren?
b) Wat heeft multicollineariteit met deze keuze te maken?
c) Wat zegt de LR-toets voor de hele factor seizoen? Is die uitslag relevant voor het wel/niet weglaten?
d) Algemenere vraag: wanneer is “weglaten op basis van -waarde” een verdedigbare strategie, en wanneer niet?
OpgeletAntwoord T10 — open na je eigen poging
a) Je kunt een dummy niet zomaar weglaten: dummies bij een factor horen samen — als je seizoenherfst schrapt, codeer je impliciet herfst samen met de referentie (bv. lente), wat inhoudelijk niet klopt. Wel kun je de hele factor weglaten, of niveaus samenvoegen op theoretische gronden.
b) Bij MRA is “een niet-significante voorspeller weglaten” verdedigbaar als hij geen unieke variantie verklaart. Maar bij sterke multicollineariteit kan hij niet-significant lijken terwijl hij wél bijdraagt — alleen samen met een collineaire collega. Eerst VIF checken, dan beslissen.
c) Als de LR-toets op de hele factor significant is (bv. , ), dan zit er als geheel signaal in seizoen, ook al ziet één dummy er los niet-significant uit. Sterk argument om de hele factor in het model te houden.
d)Wel verdedigbaar: als je vooraf een datagestuurde model-selectie-strategie (bv. backward elimination) hebt aangekondigd, of als de inhoud zegt “deze voorspeller hoorde er sowieso niet thuis”. Niet verdedigbaar: als je achteraf gaat shoppen tot het mooi uitkomt — dat is HARKing. Hou je vooraf vast aan een theoretische voorspeller-set en rapporteer alles wat je probeerde.
Inzicht. Een -waarde is geen weeg-maat voor “model-fitness van een voorspeller”. Het is een toetsingsuitkomst onder veronderstelde nul-hypothese. Modelreductie verdient een doordachte strategie, niet ad-hoc-knippen.
R-spiekblad bij LRA
Alle commando’s op één plek
Pakketten en data laden
# Pakketten activeren — één keer per sessie.library(car) # voor vif() en Anova(., test = "LR")library(dplyr) # alleen voor de dplyr-tabbladenlibrary(tidyr) # voor pivot_wider() in de dplyr-kruistabel# Hoofd-dataset laden — object 'pad_spiegel' verschijnt vanzelf.load("data/pad_spiegel.RData")str(pad_spiegel)# Mini-dataset voor E5.load("data/kerkuil_nacht.RData")
# Aantallen per uitkomst-categorie en proportie.table(pad_spiegel$bekeek_zichzelf)prop.table(table(pad_spiegel$bekeek_zichzelf))# Kruistabel factor x Y.table(pad_spiegel$diersoort, pad_spiegel$bekeek_zichzelf)
# Aantallen per uitkomst-categorie en proportie.pad_spiegel |>count(bekeek_zichzelf) |>mutate(proportie = n /sum(n))# Kruistabel factor x Y.pad_spiegel |>count(diersoort, bekeek_zichzelf) |>pivot_wider(names_from = bekeek_zichzelf, values_from = n)
# Boxplot continue X per uitkomst.boxplot(leeftijd ~ bekeek_zichzelf, data = pad_spiegel)boxplot(aantal_afwijzingen ~ bekeek_zichzelf, data = pad_spiegel)
Model fitten — glm(..., family = binomial(link = "logit"))
# Het LRA-model — let op family-argument.m_pad <-glm(bekeek_zichzelf ~ leeftijd + aantal_afwijzingen + diersoort,data = pad_spiegel,family =binomial(link ="logit"))# Coëfficiënten en Wald-z per coëfficiënt.summary(m_pad)
Coëfficiënten en odds ratios
# Log-odds-coëfficiënten.coef(m_pad)# Odds ratios.exp(coef(m_pad))# 95%-CI op log-odds-schaal.confint.default(m_pad)# 95%-CI op odds-schaal.exp(confint.default(m_pad))
Modelvergelijking via likelihood ratio
# Null-model (alleen intercept).m_null <-glm(bekeek_zichzelf ~1,data = pad_spiegel,family =binomial(link ="logit"))# Volledig model versus null.anova(m_null, m_pad, test ="Chisq")# LR-toets per term (factor als geheel).car::Anova(m_pad, type ="II", test.statistic ="LR")
Pseudo- van Hosmer en Lemeshow
# Via log-likelihoods.LL_null <-as.numeric(logLik(m_null))LL_full <-as.numeric(logLik(m_pad))1- LL_full / LL_null# Equivalent via deviances.1- m_pad$deviance / m_pad$null.deviance
Hiërarchische LRA — blok voor blok
# Elk model één blok groter dan het vorige, op dezelfde data.m_h0 <-glm(bekeek_zichzelf ~1, data = pad_spiegel, family =binomial(link ="logit"))m_h1 <-glm(bekeek_zichzelf ~ diersoort, data = pad_spiegel, family =binomial(link ="logit"))m_h2 <-glm(bekeek_zichzelf ~ diersoort + leeftijd, data = pad_spiegel, family =binomial(link ="logit"))m_h3 <-glm(bekeek_zichzelf ~ diersoort + leeftijd + aantal_afwijzingen,data = pad_spiegel, family =binomial(link ="logit"))# Per blok: chi2 (kolom Deviance), df en p.anova(m_h0, m_h1, m_h2, m_h3, test ="Chisq")# R2_L per model.r2_L <-function(m) (m$null.deviance - m$deviance) / m$null.deviancesapply(list(m_h1, m_h2, m_h3), r2_L)
# Log-odds-lineariteit: bin de continue X, plot empirische logit.qs <-quantile(pad_spiegel$leeftijd, probs =seq(0, 1, length.out =7))bins <-cut(pad_spiegel$leeftijd, breaks = qs, include.lowest =TRUE)agg <-aggregate(bekeek_zichzelf ~ bins, data = pad_spiegel, FUN = mean)agg$logit <-log(pmin(pmax(agg$bekeek_zichzelf, 0.01), 0.99) / (1-pmin(pmax(agg$bekeek_zichzelf, 0.01), 0.99)))plot(seq_along(agg$logit), agg$logit, type ="b")
# Log-odds-lineariteit: per groepje leeftijd het aandeel turers, en dat# omgezet naar log-odds. group_by() + summarise() = per groep samenvatten.per_bin <- pad_spiegel |>mutate(bin =cut(leeftijd,breaks =quantile(leeftijd, probs =seq(0, 1, length.out =7)),include.lowest =TRUE)) |>group_by(bin) |>summarise(p =mean(bekeek_zichzelf)) |>mutate(p_begrensd =pmin(pmax(p, 0.01), 0.99),logit =log(p_begrensd / (1- p_begrensd)))plot(seq_along(per_bin$logit), per_bin$logit, type ="b")
Voorbeeld-tentamenvragen
Even oefenen op tentamen-toon
Onderaan dit hoofdstuk staan vier korte theorievragen in tentamen-stijl en één mini R-opdracht. Geen verhaal-frame meer: hier oefen je zoals op het tentamen. Hou de vuistregels paraat: als vermenigvuldigingsfactor, het interval , uit twee deviances, per blok de van het verschil in deviance met = het aantal coëfficiënten dat erbij komt, sensitiviteit en specificiteit langs de rijen en PPV en NPV langs de kolommen, VIF onder , , Wald versus LR. Het hele lijstje staat bovenaan het thema, onder Wat je na dit thema moet kunnen.
Theorie en handreken
OpmerkingVraag E1 — OR aflezen en interpreteren
Een vleermuis registreert per nachtelijke vlucht of er prooi gevangen is (succes ja/nee), met als voorspellers maan-helderheid en windsnelheid. Hij rapporteert:
Estimate Std.Error z value Pr(>|z|)
(Intercept) 0.812 0.620 1.31 .190
maan_helderheid -2.140 0.820 -2.61 .009
windsnelheid -0.085 0.041 -2.07 .038
Wat is de odds ratio voor maan-helderheid, en hoe interpreteer je hem?
; per eenheid maan-helderheid daalt de kans op succes met .
; per eenheid maan-helderheid (volle maan = 1) worden de odds van succes met factor vermenigvuldigd — donker maakt jagen veel succesvoller.
; volle maan verhoogt de kans op succes drastisch.
; geen geldige interpretatie.
OpgeletAntwoord E1 — open na je eigen poging
b) . Negatief betekent OR onder — donkerder geeft meer succes. Optie a verwart met OR, c heeft het teken verkeerd, d is geen geldige formule.
OpmerkingVraag E2 — versus uit summary
Een marterspecht meet of een nestvogel een ei laat liggen na verstoring (laat-vallen ja/nee), met als voorspeller “verstoring-intensiteit” (continu, schaal 0-10):
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -3.20 0.85 -3.76 < .001
verstoring_intensiteit 0.62 0.18 3.44 < .001
Welke uitspraak is correct?
Per eenheid verstoring stijgt de kans op laat-vallen met .
Per eenheid verstoring stijgt de log-odds met ; de odds vermenigvuldigen met .
De odds ratio is — een effect onder , dus verstoring verlaagt de kans.
De -waarde is significant; daarom is de OR per definitie .
OpgeletAntwoord E2 — open na je eigen poging
b) is op de log-odds-schaal; de OR is . Optie a verwart kans met odds, c verwart met OR (negatief zou onder geven, niet ), d zegt iets onzinnigs.
Een uil bouwt een logistisch model voor jacht-succes. De confusion matrix:
predicted
observed 0 1
0 72 18
1 20 60
Wat is de accuracy en de sensitivity?
Accuracy ; sensitivity .
Accuracy ; sensitivity .
Accuracy ; sensitivity .
Accuracy ; sensitivity .
OpgeletAntwoord E3 — open na je eigen poging
a) Accuracy . Sensitivity . Optie b verwart sensitivity met specificity, c heeft sensitivity verkeerd, d wisselt accuracy en sensitivity om.
OpmerkingVraag E4 — Pseudo- aflezen en interpreteren
Een onderzoek-coördinator runt een logistisch model en rapporteert:
Null deviance: 220.4 on 159 degrees of freedom
Residual deviance: 168.6 on 154 degrees of freedom
Welke uitspraak past het best?
De pseudo-; een uitzonderlijk slecht model.
De pseudo-; het model haalt zo’n van de deviance van het null-model weg.
De pseudo-; geen geldige waarde.
Pseudo- kan niet berekend worden uit deviances; je hebt de log-likelihoods nodig.
OpgeletAntwoord E4 — open na je eigen poging
b) . Equivalent: . Het model haalt dus ruim een vijfde van de deviance van het null-model weg. Optie a verwart de breuk-kant, c is rekenkundig onzinnig, d is fout (deviance , dus pseudo- valt direct uit deviances af te leiden).
R-practical opdrachtje
De nacht van de kerkuil
OpmerkingVraag E5 — Mini-LRA bij de kerkuil
Een ecoloog onderzoekt het nachtelijke gedrag van verschillende dieren in het revier van een kerkuil — elk dier op één eigen nacht geobserveerd. Per dier wordt genoteerd of het onrustig sliep (sliep_onrustig, /) en drie voorspellers: aantal_zorgen (continu count, hoeveel zorgen het dier de afgelopen week had), eet_voor_slapen (continu, hapjes-frequentie ’s avonds, schaal -) en sociale_isolatie (factor: nee / ja / twijfelend). De dataset staat in data/kerkuil_nacht.RData en bevat het object kerkuil_nacht. Sla je R-commando’s op in één scriptbestand: kerkuil.R. Gebruik .
a) Fit het volledige LRA-model met glm(sliep_onrustig ~ aantal_zorgen + eet_voor_slapen + sociale_isolatie, family = binomial(link = "logit")). Welke voorspellers zijn significant volgens de Wald-toets? Rapporteer de toetsstatistiek en de p-waarde voor aantal_zorgen en eet_voor_slapen.
b) Bereken de odds ratios met en hun -CI. Wat is de OR voor aantal_zorgen, en wat zegt de richting?
c) Toets de hele factor sociale_isolatie met car::Anova(model, type = "II", test.statistic = "LR"). Is sociale_isolatie als geheel significant? Rapporteer , en .
d) Bereken de pseudo- via en de classificatie-accuratesse via een tabel met cutoff . Schrijf één APA-zin.
e) Bouw het model nu in drie blokken op: eerst sociale_isolatie, dan aantal_zorgen, dan eet_voor_slapen. Voegt elk blok significant iets toe? Rapporteer per blok , en , en per model .
a) Significant volgens Wald: aantal_zorgen (, p < .001) en eet_voor_slapen (, p = .001). Een -toets heeft geen vrijheidsgraden; wie liever de Wald- rapporteert, kwadrateert en schrijft voor aantal_zorgen . De factor sociale_isolatie heeft één significante dummy (ja vs nee: , p < .001); twijfelend is niet-significant (p = .13).
b) met de hand; R rekent met de onafgeronde en geeft , en dat getal gaat in de APA-zin. 95%-CI . Per extra zorg worden de odds van onrustig slapen bijna verdrievoudigd — meer zorgen, slechter slapen, weinig verrassend. Voor eet_voor_slapen per hapjes-eenheid.
c) Sociale_isolatie als geheel is significant: , p < .001. Geïsoleerde dieren onderscheiden zich duidelijk van niet-geïsoleerde (positief), twijfelende dieren verschillen niet significant.
d) Pseudo-; accuracy .
Een logistische regressie van onrustig-slapen op aantal zorgen, eten voor het slapen en sociale isolatie verklaarde de uitkomst significant beter dan een null-model, , p < .001, pseudo-. Meer zorgen waren geassocieerd met onrustiger slaap (, -CI , p < .001); meer hapjes voor het slapen eveneens (, , p = .001). Sociale isolatie droeg significant bij (, p < .001): geïsoleerde dieren hadden hogere odds van onrustig slapen dan niet-geïsoleerde (, , p < .001). Het model classificeerde van de dieren correct.
u_h1 <-glm(sliep_onrustig ~ sociale_isolatie,data = kerkuil_nacht, family =binomial(link ="logit"))u_h2 <-glm(sliep_onrustig ~ sociale_isolatie + aantal_zorgen,data = kerkuil_nacht, family =binomial(link ="logit"))u_h3 <-glm(sliep_onrustig ~ sociale_isolatie + aantal_zorgen + eet_voor_slapen,data = kerkuil_nacht, family =binomial(link ="logit"))# m0_uil is het null-model; per regel de toets van één blok.anova(m0_uil, u_h1, u_h2, u_h3, test ="Chisq")
# R2_L per model, met r2_L() uit de hiërarchische LRA van de pad.round(sapply(list(u_h1, u_h2, u_h3), r2_L), 3)
[1] 0.045 0.249 0.328
e) Ja, alle drie de blokken voegen significant iets toe. Sociale isolatie (blok 1, twee dummies): , p = .026, . Aantal zorgen erbij (blok 2): , p < .001, . Eten voor het slapen erbij (blok 3): , p < .001, . Het laatste model is hetzelfde als het volle model uit a: zijn van is de uit d, alleen op drie decimalen.
Wat blijft liggen
Onderwerpen die buiten dit thema blijven
LRA met logit-link en Hosmer-Lemeshow pseudo- is de hoofdingang van logistische analyse, maar er ligt veel achter. Wat dit oefenboek je gaf is genoeg voor de gangbare onderzoeks-rapportage; voor verdere studie:
Probit, multinomial en ordinal logistic regression — alternatieve link-functies (probit) of meerdere uitkomst-categorieën (multinomial, ordinal). Niet behandeld; dit oefenboek blijft bij binaire LRA met logit.
Penalized regression (ridge, lasso, elastic net) — voor predictieve modellen met veel voorspellers en/of weinig events. Lasso doet automatische voorspeller-selectie via -shrinkage.
ROC-curve en AUC — alternatieve evaluatie voorbij accuracy/PPV/NPV. Toont sensitivity tegen over alle cutoff-keuzes; AUC vat het in één getal samen, ongevoelig voor prevalentie.
Mixed-effects logistische regressie — voor geclusterde binaire data (bv. herhaalde metingen per persoon, leerlingen genest in scholen). Pakket lme4::glmer().
Cox-Snell en Nagelkerke pseudo- — varianten van pseudo- die we hier niet behandelen. Cox-Snell heeft een maximumwaarde onder ; Nagelkerke is daar voor gecorrigeerd. In SPSS-uitvoer staan ze er wel, naast de ; de in dit hoofdstuk is die van Hosmer en Lemeshow, en die reken je zelf uit die ’s.
Bayesiaanse logistische regressie — alternatief inferentie-frame met posterior-distributies in plaats van -waardes; toegankelijke ingangen via brms of rstanarm.
Class-imbalance handling — bij sterk scheve uitkomstverdelingen (bv. events): oversampling, undersampling, threshold-tuning, of cost-sensitive learning.
Splines en GAM voor niet-lineaire voorspellers — mgcv::gam(family = binomial) als log-odds-lineariteit niet houdt.
Voor verdieping: Hosmer, Lemeshow & Sturdivant (2013, Applied Logistic Regression); Agresti (2018, An Introduction to Categorical Data Analysis); Long (1997, Regression Models for Categorical and Limited Dependent Variables).
Aan het eind van de dag
Toen het laat werd, klapte de pad zijn schrift dicht.
“Het zijn vooral de vossen,” zei hij. “Tien keer hogere odds dan de reeën. Dassen vrijwel nooit. Een tweedeling waar ik wat aan heb.”
“En de jongere dieren,” vervolgde hij. “Ieder jaar dat ze ouder worden, dalen de odds met zo’n 14 procent. Volwassenen hebben blijkbaar wel betere dingen te doen dan in het water staren.”
“En de afgewezen dieren?” vroeg de bever, die langs zwom om zijn aantekeningen te halen.
“Die ook,” zei de pad. “Per afwijzing een derde meer odds. Wie net is gepasseerd, wil even controleren of hij nog wel een gezicht heeft.”
“Driekwart van mijn schattingen klopt,” voegde hij toe. “Niet alles. Maar genoeg om te weten wie er morgen langs het water zal komen om zichzelf eens goed in de ogen te kijken.”
“Driekwart is meer dan ik vroeger had,” zei de bever.
Ze zaten bij het water. Iemand had ergens een tak laten vallen. Hij dreef voorbij. Een ree liep in de verte langs, schichtig, en bleef even staan bij de waterspiegel. De pad keek niet meer op.
Verantwoording
Dit oefenboek is geschreven voor studenten die logistische regressieanalyse leren via R. De didactische lijnen volgen de gangbare opbouw van Nederlandse universitaire MVDA-cursussen; alle voorbeelden, datasets, vragen en formuleringen in dit hoofdstuk zijn origineel. De gebruikte drempels en formules zijn standaard statistische conventies; verwijzingen naar Pedhazur (1997) en Hosmer-Lemeshow-Sturdivant (2013) volgen de gebruikelijke citaatpraktijk in dit veld.