Frederick
Frederick

Reputation: 850

R: Propensity Score Matching using MatchIt. How to find the number of matched observations with replace = TRUE?

Please consider the following:

I am matching data with the MatchIt package in R. I have fewer controls than treated and use the option replace = TRUE. According to the manual, the weights tell us the frequence of the matched controls.

From the manual:

"For matching with replacement, use replace = TRUE. After matching with replacement, the weights can be used to reflect the frequency with which each control unit was matched."

However, I don't understand why the weights can have decimals and how that would reflect the frequency.

For example, I added replace == TRUE to the example in the manual (see page 18):

library("dplyr")
library("MatchIt")

m.out1 <- matchit(treat ~ re74 + re75 + age + educ, data = lalonde,
 method = "nearest", distance = "logit", replace = T)

tail(match.data(m.out1), 15)
#>         treat age educ black hispan married nodegree re74 re75      re78
#> PSID388     0  19   11     1      0       0        1    0    0 16485.520
#> PSID390     0  48   13     0      0       1        0    0    0     0.000
#> PSID392     0  17   10     1      0       0        1    0    0     0.000
#> PSID393     0  38   12     0      0       1        0    0    0 18756.780
#> PSID396     0  48   14     0      0       1        0    0    0  7236.427
#> PSID398     0  17    8     1      0       0        1    0    0  4520.366
#> PSID400     0  37    8     1      0       0        1    0    0   648.722
#> PSID401     0  17   10     1      0       0        1    0    0  1053.619
#> PSID407     0  23   12     0      0       0        0    0    0  3902.676
#> PSID409     0  17   10     0      0       0        1    0    0 14942.770
#> PSID411     0  18   10     1      0       0        1    0    0  5306.516
#> PSID413     0  17   10     0      0       1        1    0    0  3859.822
#> PSID419     0  51    4     1      0       0        1    0    0     0.000
#> PSID423     0  27   10     1      0       0        1    0    0  7543.794
#> PSID425     0  18   11     0      0       0        1    0    0 10150.500
#>          distance weights
#> PSID388 0.4067545     0.6
#> PSID390 0.4042321     1.2
#> PSID392 0.3974677     0.6
#> PSID393 0.4016920     4.2
#> PSID396 0.4152715     0.6
#> PSID398 0.3758217     1.8
#> PSID400 0.3595084     0.6
#> PSID401 0.3974677     1.2
#> PSID407 0.4144044     1.8
#> PSID409 0.3974677     0.6
#> PSID411 0.3966277     1.2
#> PSID413 0.3974677     1.2
#> PSID419 0.3080590     0.6
#> PSID423 0.3890954     1.2
#> PSID425 0.4076015     1.2

For control "PSID393" the weight is 4.276. Hence, I would assume that this control was matched 4 or 5 times (after rounding).

We can however also look at the match.matrix to see the matched treatment and controls one by one. Filtering for "PSID393", we see that the control has actually been matched 7 times:

m.out1$match.matrix %>% data.frame() %>% filter(X1 == "PSID393")


#>        X1
#> 1 PSID393
#> 2 PSID393
#> 3 PSID393
#> 4 PSID393
#> 5 PSID393
#> 6 PSID393
#> 7 PSID393

Created on 2019-05-06 by the reprex package (v0.2.1)

How can interpret these two outputs correctly?

Upvotes: 2

Views: 1594

Answers (1)

eipi10
eipi10

Reputation: 93851

The weights are scaled so that they sum to the number of unique matched observations in the control group. Using your example data, note that the sum of the weights is equal to the number of observations and the mean weight is 1. In addition, the weight of the most used observation(s) is seven times that of the least used observation(s):

match.data(m.out1) %>%
  group_by(treat) %>% 
  summarise(min.weight=min(weights),
            max.weight=max(weights),
            mean.weight=mean(weights),
            sum.weights=sum(weights),
            n=n(),
            max.match.ratio=max.weight/min.weight)
  treat min.weight max.weight mean.weight sum.weights     n max.match.ratio
1     0      0.605       4.24           1         112   112               7
2     1      1           1              1         185   185               1

To look at the distribution of weights, we can do:

match.data(m.out1) %>% 
  group_by(treat, weights) %>% 
  tally %>% 
  group_by(treat) %>% 
  mutate(weight.ratio = weights/min(weights))
  treat weights     n weight.ratio
1     0   0.605    74            1
2     0   1.21     19            2
3     0   1.82     10            3
4     0   2.42      6            4
5     0   3.63      2            6
6     0   4.24      1            7
7     1   1       185            1

There's a FAQ at the end of the MatchIt vignette. Item 5.3, "How Exactly are the Weights Created?" notes that "The control group weights are scaled to sum to the number of uniquely matched control units."

Upvotes: 3

Related Questions