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:
Das Kovariaten-Matching kann mit Hilfe des Pakets
MatchIt
durchgeführt werden. Die darin enthaltene Funktion
matchit()
erlaubt es, zwei Gruppen hinsichtlich
verschiedener Kovariaten zu matchen. Die folgende Tabelle bietet eine
Übersicht der zentralen Funktionsargumente von
matchit()
:
Argument | Bedeutung |
---|---|
matchit( |
|
treat ~ x1 + x2, |
Angabe der Interventionsvariable (treat )
und einer oder mehrerer Kovariaten (x1 + x2 + ... ) |
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 des Propensity-Scores (z.B.
distance = "glm" für generalized linear model;
default) |
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 |
std.caliper, |
Angabe des Caliper in Standardabweichungen
(std.caliper = TRUE , default) oder in Rohwerten
(std.caliper = FALSE ) |
caliper, |
Größe des Caliper für die Matches auf den
kontinuierlichen Kovariaten. Der default ist, keinen Caliper
(caliper = NULL ) festzulegen |
replace) |
Angabe, ob mit (replace = TRUE ) oder ohne
Zurücklegen (replace = FALSE , default) gezogen wird. |
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. bei Mittelwertsdifferenzen
thresholds = c(-0.1, 0.1) entspricht den Grenzen
akzeptabler (standardisierter) Mittelwertsdifferenzen nach Steiner et
al. (2010) |
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 vor der ersten Nutzung des Pakets MatchIt
library(MatchIt) # Laden des Paketes
# install.packages("cobalt") # Installation vor der ersten Nutzung des Pakets cobalt
library(cobalt) # Laden des Paketes
Anschließend lesen wir 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)
Nun wird mit Hilfe der matchit()
-Funktion gematcht. Wir
zeigen das Kovariaten-Matching hier beispielhaft mit der
“Nearest-Neighbor”-Methode, der Mahalanobis-Distanz als Distanzmetrik,
einem 1:1-Verhältnis, ohne Zurücklegen und mit einem Caliper von 0,1
Standardabweichungen.
near <- matchit(treat ~ eng_pre + eng_vorliebe, # Matching über Interventionsgruppen (treat)
# anhand der Kovariaten
# eng_pre und eng_vorliebe
data = englisch, # der Datensatz
method = "nearest", # Nearest-Neighbour-Matching
distance = "mahalanobis", # Mahalanobis-Distanz als Distanzmetrik
ratio = 1, # 1:1-Matching
replace = FALSE, # ohne Zurücklegen
std.caliper = TRUE, # Caliper wird in Standardabweichungen
# angegeben
caliper = c(eng_pre = 0.1) # Maximal 0,1 Standardabweichungen
# Differenz zwischen den Personen
# erlaubt auf der kontinuierlichen
# Kovariate
)
Über den summary()
-Befehl können wir uns die Ergebnisse
des Matchings ausgeben lassen. Die relevanten Abschnitte des Outputs
werden nacheinander gezeigt und erläutert.
summary(near) # Ergebnis des Matchings
Wir schauen uns zunächst an, wie viele Personen gematcht wurden, wie viele nicht gematcht wurden und wie viele aufgrund von Nicht-Überlappung entfernt wurden:
...
## Sample Sizes:
## Control Treated
## All 232 210
## Matched 146 146
## Unmatched 86 64
## Discarded 0 0
...
Unter Sample
Sizes können wir uns ansehen, welcher Anteil unserer
ursprünglichen Daten gematcht und somit verwendet wird. Die
Kontrollgruppe umfasst in der Gesamtstichprobe 232
Personen, die Interventionsgruppe 210
Personen. Gematcht
wurden jeweils 146
Personen. Für 86
Personen
aus der Kontrollgruppe und 64
aus der Interventionsgruppe
wurde kein:e Matchingpartner:in gefunden.
Im Folgenden prüfen wir die Balance sowohl anhand von Verteilungskennwerten als auch anhand der Verteilungen.
...
## Summary of Balance for All Data:
## Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean eCDF Max
## eng_pre 2.78 2.4 0.915 0.586 0.216 0.355
## eng_vorliebe 0.70 0.5 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.
## eng_pre 2.651 2.650 0.001 0.995 0.007 0.041 0.041
## eng_vorliebe 0.575 0.514 0.135 . 0.062 0.062 0.344
##
## Sample Sizes:
## Control Treated
## All 232 210
## Matched 146 146
## Unmatched 86 64
## Discarded 0 0
...
Es werden die Kennwerte der Kovariaten in Interventions- und Kontrollgruppe oder deren Verhältnis für die gesamte Stichprobe (Summary of Balance for All Data) und nach dem Matching nur 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. An dieser Stelle sei erwähnt, dass es auch andere Vorschläge dazu gibt, ab welchen Werten von einer ausreichenden Balance gesprochen werden kann. So betragen beispielsweise die von Stuart & Rubin (2008) vorgeschlagenen, weniger strengen Grenzen für akzeptable standardisierte Mittelwertsdifferenzen -0,25 und 0,25 und für akzeptable Varianzverhältnisse 0,5 und 2.
All Data:
Vor dem Matchen liegt eine deutliche Imbalance der
Kovariatenausprägungen über die beiden Interventionsgruppen vor. Die
Interventionsgruppe hat vor dem Matching im Durchschnitt um 0,38 Punkte
(2,780
- 2,400
) bessere Englischvorkenntnise
als die Kontrollgruppe. Dieser Unterschied entspricht einem Cohen’s
\(d\) von 0,915
(Std. Mean Diff.) und somit
einer großen Differenz, die deutlich von den von Steiner et al. (2010)
vorgeschlagenen Grenzen für akzeptable standardisierte
Mittelwertsdifferenzen betragen (zwischen -0,1 und 0,1) abweicht. Das
Varianzverhältnis liegt vor dem Matching bei 0,586
. Das
bedeutet, dass die Varianz (d.h. Unterschiedlichkeit) der Vorkenntnisse
innerhalb der Interventionsgruppe deutlich geringer (fast nur halb so
groß) ist wie die Varianz in den Vorkenntnissen in der Kontrollgruppe.
Die Personen in der Interventionsgruppe sind sich also in ihren
Vorkenntnissen deutlich ähnlicher als Personen in der Kontrollgruppe
untereinander. Das Varianzverhältnis liegt deutlich außerhalb des von
Steiner et al. (2010) vorgeschlagenen Bereiches für akzeptable Werte
(zwischen 0,8 und 1,25). Zudem sind Personen mit einer Vorliebe für
Englisch in der Interventionsgruppe stärker vertreten (70
%)
als in der Kontrollgruppe (50
%).
Matched Data:
Nach dem Matching gibt es kaum noch Unterschiede in den
Englischvorkenntnissen zwischen Interventions- und Kontrollgruppe. Die
standardisierte Mittelwertsdifferenz liegt nun bei Cohen’s \(d\) = 0,001
und somit
innerhalb der von Steiner et al. (2010) vorgeschlagenen Grenzen. Das
Varianzverhältnis beträgt nach dem Matching 0,995
und liegt
damit ebenfalls innerhalb der von Steiner et al. (2010) vorgeschlagenen
Grenzen. Nach dem Matchen gibt es zwar noch einen Unterschied im Anteil
an Personen mit einer Vorliebe für Englisch (57,5
% in der
Interventions- und 51,4
% in der Kontrollgruppe), dieser
Unterschied ist jedoch nicht sehr groß. Die Ergebnisse sprechen
insgesamt für eine gute Balance.
Die Mittelwertsunterschiede können wir grafisch mit der
love.plot()
-Funktion darstellen.
love.plot(near, # 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 in der Grafiklegende
"Gematchte Stichprobe"),
stars = "raw" # Markierung nicht-standardisierter
# Mittelwertsdifferenzen
)
Das Sternchen bei eng_vorliebe zeigt an, dass hier die unstandardisierten Mittelwertsunterschiede statt der standardisierten Mittelwertsunterschiede dargestellt sind, da es sich um eine kategoriale Kovariate handelt, für die die Berechnung von Cohen’s \(d\) nicht sinnvoll ist.
Wie wir schon aus dem Output oben entnehmen konnten, ist der Mittelwertunterschied von eng_pre zwischen Interventions- und Kontrollgruppe vor dem Matchen sehr groß. Nach dem Matchen liegt er aber nahe null und innerhalb der von Steiner et al. (2010) vorgeschlagenen Grenzen für akzeptable (standardisierte) Mittelwertsdifferenzen von -0,1 und 0,1 (d.h. innerhalb der gestrichelten vertikalen Linien).
Auch die Varianzverhältnisse können wir in einem Love Plot
darstellen. Dazu ändern wir das Argument stats
(und die
zugehörigen Grenzwerte):
love.plot(near, # 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")
)
In unserem Beispiel gibt es nur eine kontinuierliche Kovariate (eng_pre). In der Grafik können wir erkennen, dass das Varianzverhältnis von eng_pre zwischen Interventions- und Kontrollgruppe vor dem Matchen mit unter 0,6 deutlich unter den von Steiner et al. (2010) vorgeschlagenen Grenzen für akzeptable Varianzverhältnisse (d.h. außerhalb der gestrichelten vertikalen Linien) liegt. Nach dem Matchen liegt es nahe 1, die Varianzen der Interventions- und der Kontrollgruppe sind also nach dem Matchen fast identisch.
Mittelwerte und Varianzen stellen nur Teilaspekte der Verteilung dar. Um ein umfassendes Bild der Balance zu bekommen, können wir uns auch die Verteilung kontinuierlicher Kovariaten (z.B. Englischvorkenntnisse) in den zwei Gruppen vor und nach dem Matching ansehen.
bal.plot(near, # matchit-Objekt
var.name = "eng_pre", # Variable, für die die Kovariatenverteilung
# dargestellt werden soll
which = "both", # Kovariatenverteilung vor und nach
# Matching anzeigen lassen
type = "histogram", # Darstellung als Histogramm
mirror = TRUE, # Spiegelung der gruppenspezifischen
# Verteilungen an x-Achse
sample.names = c("Gesamtstichprobe", # Namen für Stichproben in der Grafiklegende
"Gematchte Stichprobe"))
Vor dem Matchen unterscheiden sich die beiden Interventionsgruppen hinsichtlich der Verteilung der Englisch-Vorkenntnisse deutlich. Nach dem Matchen ist die Verteilung der Englisch-Vorkenntnisse in den Gruppen fast identisch. Dies spricht für eine gute Balance.
Um den Effekt unseres Englisch-Trainings auf die Englischkentnisse zu
schätzen, extrahieren wir die Daten der gematchten Personen mithilfe des
match.data()
-Befehls und schätzen dann auf Basis der
gematchten Daten eine Regression des Englisch-Nachtests auf die
Interventionsvariable:
near_data <- match.data(near)
m1 <- lm(eng_post ~ treat, # Regression von Englisch-Nachtest
# auf die Interventionsvariable
data = near_data) # der neue Datensatz
summary(m1) # Ergebnis des Regressionsmodells
##
## Call:
## lm(formula = eng_post ~ treat, data = near_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.3019 -0.3519 -0.0242 0.3476 1.4777
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.9842 0.0433 68.89 < 0.0000000000000002 ***
## treat 0.2438 0.0613 3.98 0.000087 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.523 on 290 degrees of freedom
## Multiple R-squared: 0.0518, Adjusted R-squared: 0.0485
## F-statistic: 15.8 on 1 and 290 DF, p-value: 0.0000871
Der Regressionskoeffizient für die Interventionsvariable
(0,244
) ist der Schätzer für den kausalen Effekt. Wir
schätzen, dass das Englischtraining in der gematchten Stichprobe die
Englischkenntnisse im Mittel um 0,244 Punkte (SE = 0,061
)
erhöht (im Vgl. zu keinem Englischtraining). Dieser Effekt ist
signifikant von null verschieden (\(t(1)\) = 3,980
, \(p\) < ,001
).
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.1093/pan/mpl013
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/a0018719
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