Wir möchten evaluieren, ob ein entwickeltes Englischtraining die
Englischkenntnisse von Studierenden erhöht. Dazu wurde eine
quasi-experimentelle Studie durchgeführt, bei der die Studierenden
selbst entscheiden konnten, ob sie am Training teilnehmen
(Interventionsgruppe; IG) oder nicht (Kontrollgruppe; KG). Nach dem
Training wurden in beiden Gruppen die Englischkenntnisse gemessen. Als
Kovariaten wurden die Englischvorkenntnisse und die Vorliebe für
Englisch erhoben. Für die Analysen nutzen wir den simulierten Datensatz
(englisch.rda
) mit dem Objektnamen englisch
mit den folgenden Variablen:
Für das PS-Matching verwenden wir die Funktion matchit()
aus dem Paket MatchIt
. Die zentralen Elemente der Funktion
werden im Folgenden erklärt:
Argument | Bedeutung |
---|---|
matchit( |
|
treat ~ x1 + x2, |
Angabe der Regressionsgleichung einer
Interventionsvariable (treat ) auf eine oder mehrere
Kovariaten (x1 , x2 , …) für die Schätzung der
Propensity-Scores |
data, |
Datensatz |
method, |
Wahl der Matchingmethode; z.B.
Nearest-Neighbour-Matching (method = "nearest" , default),
exaktes Matching (method = "exact" ) oder Optimal-Matching
(method = "optimal" ) |
distance, |
Wahl des Distanzmaßes (z.B. direkte Eingabe einer
Distanz), einer Methode zur Berechnung der Distanz (z.B.
distance = "mahalanobis" für die Mahalanobis-Distanz) oder
einer Methode zur Schätzung der Propensity-Scores (z.B.
distance = "glm" für generalized linear model;
default) |
link, |
Art der link-Funktion bei der Schätzung der PS; z.B.
link = "logit" für logistische Funktion |
ratio, |
Anzahl der Matchingpartner:innen in der Kontrollgruppe
für jede Person in der Interventionsgruppe; z.B. 1:1-Matching
(ratio = 1 , default) oder 1:2-Matching
(ratio = 2 ) mit 2 Matchingpartner:innen in der
Kontrollgruppe für jede Person in der Interventionsgruppe |
caliper, |
Größe des Caliper für die Matches auf den
kontinuierlichen Kovariaten. Der default ist, keinen Caliper
(caliper = NULL ) festzulgen |
std.caliper, |
Angabe des Caliper in Standardabweichungen
(std.caliper = TRUE , default) oder in Rohwerten
(std.caliper = FALSE ) |
replace, |
Angabe, ob mit (replace = TRUE ) oder ohne
Zurücklegen (replace = FALSE , default) gezogen wird |
discard) |
Angabe, ob Daten, die nicht Teil der Region of Common
Support sind, ausgeschlossen werden sollen; z.B.
discard = "both" , wenn Personen der Interventionsgruppe und
Kontrollgruppe ausgeschlossen werden sollen,
discard = "treated" , wenn nur Personen aus der
Interventionsgruppe und discard = "control" , wenn nur
Personen der Kontrollgruppe ausgeschlossen werden sollen; bei
discard = "none" werden keine Daten ausgeschlossen
(default) |
Mit der Funktion love.plot()
aus dem Paket
cobalt
können Unterschiede in Verteilungskennwerten auf den
Kovariaten vor und nach dem Matching visualisiert werden. Die relevanten
Argumente der Funktion sind in der folgenden Tabelle erklärt.
Argument | Bedeutung |
---|---|
love.plot( |
|
x, |
matchit -Objekt |
stats, |
Kennwerte, die dargestellt werden sollen; z.B.
stats = "mean.diffs" für Mittelwertdifferenzen,
stats = "variance.ratios" für Varianzverhältnisse |
thresholds, |
Markierung von Grenzwerten für eine akzeptable Balance
(optional); z.B. nach Steiner et al. (2010) für Mittelwertsdifferenzen
thresholds = c(-0.1, 0.1) |
sample.names, |
frei wählbare Namen für die ungematchte und gematchte
Stichprobe in der Grafik; z.B.
sample.names = c("Gesamtstichprobe", "Gematchte Stichprobe") |
stars) |
Angabe von Variablenarten, die in der Grafik mit einem
Stern markiert werden sollen; z.B. stars = "raw" für
Variablen mit nicht-standardisierten Mittelwertdifferenzen |
Mit der Funktion bal.plot()
aus dem Paket
cobalt
können die Verteilungen der Kovariaten zwischen den
Interventionsgruppen vor und nach dem Matching visualisiert werden. Die
relevanten Argumente der Funktion sind in der folgenden Tabelle
erklärt.
Argument | Bedeutung |
---|---|
bal.plot( |
|
x, |
matchit -Objekt |
var.name, |
Variable, für die die Kovariatenbalance dargestellt werden soll |
which, |
Angabe, welche Verteilungen dargestellt werden sollen;
z.B. which = "both" für beide Stichproben;
which = "unadjusted" nur für Gesamtstichprobe;
which = "adjusted" nur für gematchte Stichprobe |
type, |
Art der Darstellungsform; z.B.
type = "histogram" für ein Histogramm;
type = "density" für Dichtefunktion |
mirror, |
Spiegelung gruppenspezifischer Verteilung an der
x-Achse bei mirror = TRUE |
sample.names) |
frei wählbare Namen für die ungematchte und gematchte
Stichprobe in der Grafik; z.B.
sample.names = c("Gesamtstichprobe", "Gematchte Stichprobe") |
Zunächst installieren (falls nötig) und laden wir die nötigen Pakete
# install.packages("MatchIt") # Installation des Paketes MatchIt vor der ersten Nutzung
library(MatchIt) # Laden des Paketes
# install.packages("cobalt") # Installation des Paketes cobalt vor der ersten Nutzung
library(cobalt) # Laden des Paketes
und lesen den Datensatz ein
load("englisch.rda") # Einlesen des Datensatzes (wenn der Datensatz nicht
# im Arbeitsverzeichnis liegt, muss der Pfad entsprechend
# dem Speicherort des Datensatzes angepasst werden)
Wir zeigen das PS-Matching hier beispielhaft mit der “Nearest-Neighbor”-Methode, einem 1:1-Verhältnis, ohne Zurücklegen und mit einem Caliper von 0,1 Standardabweichungen. Die Propensity-Scores werden auf der Basis der glm-Funktion mit einem logit-Link berechnet.
ps_matching <- matchit(treat ~ eng_pre + eng_vorliebe, # Schätzung der Propensity Scores
# mit dem entsprechenden Modell
# Vorhersage der Interventionsgruppe additiv
# anhand der beiden Kovariaten
data = englisch, # der Datensatz
method = "nearest", # "Nearest-Neighbor"-Matching
distance = "glm", # Berechnung der PS auf Basis der
# glm-Funktion
link = "logit", # mit logit Link
ratio = 1, # 1:1-Matching
replace = FALSE, # ohne Zurücklegen
caliper = 0.1, # Maximal 0,1 Standardabweichungen Differenz
# auf dem Distanzmaß zwischen zwei
# Matchingpartner:innen erlaubt
discard = "both") # Personen außerhalb der Region of Common
# Support werden ausgeschlossen
Über den summary()
-Befehl lassen wir uns die Ergebnisse
des Matchings anzeigen.
summary(ps_matching)
Schauen wir uns zunächst die Anzahl der gematchten Personen an.
...
## Sample Sizes:
## Control Treated
## All 232 210
## Matched 144 144
## Unmatched 77 66
## Discarded 11 0
...
Unter Sample
Sizes können wir uns ansehen, wie viele unserer
ursprünglichen Daten gematcht und somit verwendet werden. Die
Kontrollgruppe umfasst in der Gesamtstichprobe 232
Personen, die Interventionsgruppe 210
Personen. Gematcht
wurden 144
Personen in jeder Gruppe. Für 77
Personen aus der Kontrollgruppe und für 66
Personen aus der
Interventionsgruppe wurde kein:e Matchingpartner:in gefunden. Aufgrund
mangelnden Overlaps wurden 11
Personen aus der
Kontrollgruppe ausgeschlossen (Discarded
).
Die gematchten und ungematchten Personen können wir mit der
plot()
-Funktion visualisieren.
plot(ps_matching, # matchit-Objekt
type = 'jitter', # Visualisierung der Verteilung der Propensity-Scores
# in Interventionsgruppe und Kontrollgruppe für gematchte
# und nicht gematchte Stichproben
interactive = FALSE) # (mit interactive = TRUE könnten Datenpunkte einzeln angeklickt und
# deren Position im Datensatz ausgegeben werden; wir brauchen diese
# interaktive Darstellung hier nicht)
Die Grafik gibt uns einen Überblick darüber, welche Personen
(Units
) aus Kontrollgruppe (Control
) und
Interventionsgruppe (Treated
) gematcht wurden
(Matched
) und für welche Personen keine geeigneten
Matchingpartner:innen gefunden wurden (Unmatched
). Es ist
zu sehen, dass es Personen in der Kontroll- und Interventionsgruppe
gibt, für die es Matchingpartner:innen geben würde, wenn mehr als ein:e
Matchingpartner:in zugelassen wäre. Allerdings gibt es auch Personen mit
sehr geringen Propensity-Scores in der Kontrollgruppe, für die es keine
passenden Matchingpartner:innen in der Interventionsgruppe mit ähnlich
niedrigen Propensity-Scores gibt. Diese liegen außerhalb der Region of
Common Support.
Wir können die Balance nun sowohl anhand der Verteilungskennwerte als auch anhand der Verteilungen prüfen.
summary(ps_matching)
...
## Summary of Balance for All Data:
## Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean eCDF Max
## distance 0.56 0.398 0.914 0.879 0.234 0.365
## eng_pre 2.78 2.396 0.915 0.586 0.216 0.355
## eng_vorliebe 0.70 0.500 0.436 . 0.200 0.200
##
## Summary of Balance for Matched Data:
## Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean eCDF Max Std. Pair Dist.
## distance 0.491 0.483 0.043 1.060 0.012 0.049 0.046
## eng_pre 2.641 2.622 0.044 0.808 0.035 0.097 0.517
## eng_vorliebe 0.597 0.590 0.015 . 0.007 0.007 0.924
##
## Sample Sizes:
## Control Treated
## All 232 210
## Matched 144 144
## Unmatched 77 66
## Discarded 11 0
...
Es werden Kennwerte der Verteilung der Kovariaten und der
Propensity-Scores (distance
) in Interventions- und
Kontrollgruppe für die gesamte Stichprobe
(Summary of Balance for All
Data) und nach dem Matching für die gematchten Daten
(Summary of Balance for
Matched Data) gezeigt.
Dabei bedeutet…
Bei der Beurteilung der Balance orientieren wir uns im Folgenden an den von Steiner et al. (2010) vorgeschlagenen Richtlinien für die Balance metrischer Variablen. Wir gehen demnach von Balance aus, wenn die standardisierten Mittelwertsdifferenz zwischen -0,1 und 0,1 und das Varianzverhältnis zwischen 0,8 und 1,25 liegt. Weniger strenge Grenzen wurden von Stuart und Rubin (2008) vorgeschlagen, bei denen von Balance ausgegangen wird, wenn die standardisierten Mittelwertsdifferenz zwischen -0,25 und 0,25 und das Varianzverhältnis zwischen 0,5 und 2 liegt.
All Data:
Vor dem Matchen sind deutlich Selektionseffekte sichtbar. Personen in
der Interventionsgruppe haben im Mittel einen höheren Propensity-Score
(mittlerer PS = 0,560
) als Personen in der Kontrollgruppe
(mittlerer PS = 0,398
). Diese Mittelwertsdifferenz ist groß
(Cohen’s \(d\) = 0,914
).
Die Interventionsgruppe ist sich in ihren Propensity-Scores
untereinander ähnlicher als die Kontrollgruppe; die Varianz der
Propensity-Scores in der Interventionsgruppe ist nur 0,879 mal so groß
wie die in der Kontrollgruppe (Varianzverhältnis = 0,879
).
Die Interventionsgruppe ist vor dem Matching im Durchschnitt um
(2,780
- 2,396
= ) 0,384 Punkte besser im
Englischvortest als die Kontrollgruppe. Dieser Unterschied entspricht
einem Cohen’s \(d\) von
0,915
. Die Englischkenntnisse sind in der
Interventionsgruppe deutlich homogener als die Englischkenntnisse in der
Kontrollgruppe (die Varianz in der Interventionsgruppe ist nur
0,586
mal so groß wie die Varianz in der Kontrollgruppe).
Somit liegen alle relevanten Kennwerte, bis auf das Varianzverhältnis
der Propensity-Scores, außerhalb der von Steiner et al. (2010)
vorgeschlagenen Grenzen für akzeptable Balance. Englischliebhabende sind
in der Interventionsgruppe zudem stärker vertreten (70
%)
als in der Kontrollgruppe (50
%).
Matched Data:
Nach dem Matchen unterscheiden sich die Propensity-Scores im Mittel
(Cohen’s \(d\) = 0,043
)
sowie in der Varianz (Varianzverhältnis von 1,060
) kaum
zwischen den beiden Gruppen. Auch gibt es nach dem Matchen kaum
Unterschide in den Englischvorkenntnisse zwischen Intervention- und
Kontrollgruppe (Cohen’s \(d\) =
0,044
; Varianzverhältnis = 0,808
). Der Anteil
von Englischliebhabenden unterscheidet sich nach dem Matchen zwischen
den Interventionsgruppen fast nicht mehr (59,7
% und
59,0
%). Alle relevanten Kennwerte liegen nach dem
PS-Matching innerhalb der von Steiner et al. (2010) vorgeschlagenen
Grenzen für akzeptable Balance. Nach dem Matching liegt eine
ausreichende Balance vor.
Die Mittelwertsunterschiede können wir grafisch darstellen:
love.plot(ps_matching, # matchit-Objekt
stats = "mean.diffs", # Mittelwertsdifferenzen
thresholds = c(-0.1, 0.1), # Einzeichnen der Grenzwerte nach
# Steiner et al. (2010)
sample.names = c("Gesamtstichprobe", # Namen für Stichproben
"Gematchte Stichprobe"),
stars = "raw" # Markierung nicht-standardisierter
# Mittelwertsdifferenzen
)
Wie wir schon aus dem Output oben entnehmen konnten, sind die
Mittelwertunterschiede von eng_pre und den Propensity-Scores
(distance
) zwischen Interventions- und Kontrollgruppe vor
dem Matching sehr groß und liegen außerhalb der von Steiner et
al. (2010) vorgeschlagenen Grenzen (d.h. außerhalb der gestrichelten
Linien). Nach dem Matching hingegen liegen sie jeweils nahe null und
innerhalb der Grenzen.
Ebenso können wir die Varianzverhältnisse grafisch darstellen:
love.plot(ps_matching, # matchit-Objekt
stats = "variance.ratios", # Varianzverhältnisse
thresholds = c(0.8, 1.25), # Einzeichnen der Grenzwerte nach
# Steiner et al. (2010)
sample.names = c("Gesamtstichprobe", # Namen für Stichproben in der Grafiklegende
"Gematchte Stichprobe")
)
Wie oben bereits festgestellt, liegt das Varianzverhältnis der
Propensity-Scores (distance
) zwischen Interventions- und
Kontrollgruppe bereits vor dem Matchen innerhalb der Grenzen nach
Steiner et al. (2010), nach dem Matchen liegt es ebenfalls innerhalb der
Grenzen und etwas näher an 1. Das Varianzverhältnis von eng_pre
liegt vor dem Matchen mit unter 0,6 deutlich unter den von Steiner et
al. (2010) vorgeschlagenen Grenzen, nach dem Matchen liegt es innerhalb
der Grenzen.
Wir können uns zudem die Verteilung kontinuierlicher Kovariaten (z.B. Englischvorkenntnisse) in den zwei Gruppen vor und nach dem Matching ansehen.
bal.plot(ps_matching, # matchit-Objekt
var.name = "eng_pre", # Variable, für die Kovariatenverteilungen
# dargestellt werden sollen
which = "both", # Kovariatenverteilung vor und nach Matching
type = "histogram", # Darstellung als Histogramm
mirror = TRUE, # Spiegelung der gruppenspezifischen Verteilungen an x-Achse
sample.names = c("Gesamtstichprobe", # Namen für Stichproben
"Gematchte Stichprobe"))
Die Graphik zeigt, dass die zwei Gruppen in der gematchten Stichprobe fast identisch verteilt sind, während dies vor dem Matching nicht der Fall war. Dies spricht für eine gute Balance auf dieser Kovariate nach dem Matching.
Im vorliegenden Beispiel wurde durch das PS-Matching eine ausreichende Balance hergestellt. Sollte die Prüfung der Balance einmal ergeben, dass die Mittelwertsdifferenzen zu groß, die Varianzverhältnisse zu weit von 1 entfernt sind und / oder sich die Verteilungen der Kovariaten zwischen Interventions- und Kontrollgruppe zu stark unterscheiden, muss das Modell zur Schätzung der Propensity-Scores geändert werden und ein neues Matching durchgeführt werden. Die Möglichkeiten, das Modell zur PS-Schätzung zu verändern, umfassen:
discard=“both“
), falls noch nicht
geschehencaliper
) verringernreplace = TRUE
) matchen undratio
)
verringernDiese Veränderungen können innerhalb der
matchit
-Funktion durchgeführt werden. Nach der Veränderung
des Modells muss geprüft werden, ob mithilfe des neuen Modells Balance
und Overlap gegeben sind, gegebenenfalls muss der Prozess so lange
wiederholt werden, bis ein Modell gefunden wird, mit dem eine
ausreichende Balance erzielt wird.
Um den Effekt des Englisch-Trainings auf die Englischkentnisse zu
schätzen, extrahieren wir die Daten der gematchten Personen mithilfe des
match.data()
-Befehls:
ps_data <- match.data(ps_matching)
Dann schätzen wir mit den gematchten Daten den durchschnittlichen kausalen Effekt mit Hilfe einer Regression der Englischkenntnisse im Nachtest auf die Interventionsvariable.
m1 <- lm(eng_post ~ treat, # Regression von Englisch-Nachtest
# auf die Interventionsvariable
data = ps_data) # Datensatz der gematchten Stichprobe
summary(m1) # Ergebnis des Regressionsmodells
##
## Call:
## lm(formula = eng_post ~ treat, data = ps_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.4781 -0.3511 -0.0093 0.3765 1.6287
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.9976 0.0449 66.81 < 0.0000000000000002 ***
## treat 0.2832 0.0635 4.46 0.000012 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.538 on 286 degrees of freedom
## Multiple R-squared: 0.0651, Adjusted R-squared: 0.0618
## F-statistic: 19.9 on 1 and 286 DF, p-value: 0.0000117
Der durschnittliche kausale Effekt der gematchten Stichprobe beträgt
0,283
(Regressionskoeffizient von treat). Das
bedeutet, dass das Training im Durchschnitt zu einem um 0,283 Punkte
besseren Ergebnis im Nachtest führt im Vergleich zu keinem Training.
Dieser Effekt ist statistisch signifikant (\(t(1)\) = 4,460
; \(p\) < ,001
).
Die hier angegebene Inferenzstatistik berücksichtigt nicht, dass auch die PS-Schätzung aus dem ersten Schritt mit Unsicherheit verbunden ist. Es existieren Verfahren, die diese Unsicherheit in der Inferenz für die kausalen Effekte berücksichtigen.
Weiterführende Literatur zur Umsetzung von PS-Methoden in R finden Sie hier:
Weitere Informationen zu den Paketen MatchIt und cobalt sind hier zu finden:
Greifer, N. (2022, 03. November). Covariate balance tables and plots: A guide to the cobalt package. Cran R- Project. https://cran.r-project.org/web/packages/cobalt/vignettes/cobalt_A0_basic_use.html
Ho, D. E., Imai, K., King, G., & Stuart, E. A. (2007). Matching as nonparametric preprocessing for reducing model dependence in parametric causal inference. Political Analysis, 15(3), 199-236. https://doi.org/10.18637/jss.v042.i08
Ho, D. E., Imai, K., King, G., & Stuart, E. A. (2011). MatchIt: Nonparametric Preprocessing for Parametric Causal Inference. GitHub. https://kosukeimai.github.io/MatchIt/
Benchmarks für Balance finden Sie beispielsweise hier:
Steiner, P. M., Cook, T. D., Shadish, W. R., & Clark, M. H. (2010). The importance of covariate selection in controlling for selection bias in observational studies. Psychological Methods, 15(3), 250. https://doi.org/10.1037/a001871
Stuart, E. A., & Rubin, D. B. (2008). Best practices in quasi-experimental designs: Matching methods for causal inference. In J. Osborne (Hrsg.), Best Practices in Quantitative Methods (155-176). Sage Publications. https://doi.org/10.4135/9781412995627