insongkim / PanelMatch

111 stars 34 forks source link

Mahalanobis max match size fix (new base branch) #120

Closed prestevez closed 1 year ago

prestevez commented 1 year ago

I had previously submitted a pull request to solve this bug (see: https://github.com/insongkim/PanelMatch/pull/119), but I had used the master branch as a base assuming it corresponded to the CRAN version. So I now submit the pull request incorporating the fix to the se_comparison branch, as this appears to be the newest version of the repo.

Bug

Objects created with PanelMatch refined using Mahalanobis distance are missing the max.match.size attribute.

## Using CRAN's PanelMatch v2.0.1

PM.results.none <- PanelMatch(lag = 4, time.id = "year", unit.id = "wbcode2", 
                              treatment = "dem", refinement.method = "none", 
                              data = dem, match.missing = TRUE, 
                              size.match = 5, qoi = "att", outcome.var = "y",
                              lead = 0:4, forbid.treatment.reversal = FALSE, 
                              use.diagonal.variance.matrix = TRUE)
#Extract the matched.set object
msets.none <- PM.results.none$att

#Call PanelMatch with refinement
PM.results.maha <- PanelMatch(lag = 4, time.id = "year", unit.id = "wbcode2", 
                              treatment = "dem", refinement.method = "mahalanobis", 
                              # use Mahalanobis distance 
                              data = dem, match.missing = TRUE, 
                              covs.formula = ~ tradewb, 
                              size.match = 5, qoi = "att" , outcome.var = "y",
                              lead = 0:4, forbid.treatment.reversal = FALSE, 
                              use.diagonal.variance.matrix = TRUE)

msets.maha <- PM.results.maha$att

PM.results.psm <- PanelMatch(lag = 4, time.id = "year", unit.id = "wbcode2", 
                              treatment = "dem", refinement.method = "ps.match", 
                              # use propensity score matching 
                              data = dem, match.missing = TRUE, 
                              covs.formula = ~ tradewb, 
                              size.match = 5, qoi = "att" , outcome.var = "y",
                              lead = 0:4, forbid.treatment.reversal = FALSE, 
                              use.diagonal.variance.matrix = TRUE)

msets.psm <- PM.results.psm$att

attr(msets.none, "max.match.size")
#> NULL

attr(msets.psm, "max.match.size")
#> 5

attr(msets.maha, "max.match.size")
#> NULL # <---- This should be five

prestevez/PanelMatch@mahalanobis-match-size-fix

I noticed that the attribute was not set in the helper function perform_refinement, so this was added toward the end of the function.


# Call PanelMatch without any refinement
PM.results.none <- PanelMatch(lag = 4, time.id = "year", unit.id = "wbcode2", 
                              treatment = "dem", refinement.method = "none", 
                              data = dem, match.missing = TRUE, 
                              size.match = 5, qoi = "att", outcome.var = "y",
                              lead = 0:4, forbid.treatment.reversal = FALSE, 
                              use.diagonal.variance.matrix = TRUE)
#Extract the matched.set object
msets.none <- PM.results.none$att

#Call PanelMatch with refinement
PM.results.maha <- PanelMatch(lag = 4, time.id = "year", unit.id = "wbcode2", 
                              treatment = "dem", refinement.method = "mahalanobis", 
                              # use Mahalanobis distance 
                              data = dem, match.missing = TRUE, 
                              covs.formula = ~ tradewb, 
                              size.match = 5, qoi = "att" , outcome.var = "y",
                              lead = 0:4, forbid.treatment.reversal = FALSE, 
                              use.diagonal.variance.matrix = TRUE)

msets.maha <- PM.results.maha$att

PM.results.psm <- PanelMatch(lag = 4, time.id = "year", unit.id = "wbcode2", 
                              treatment = "dem", refinement.method = "ps.match", 
                              # use propensity score matching 
                              data = dem, match.missing = TRUE, 
                              covs.formula = ~ tradewb, 
                              size.match = 5, qoi = "att" , outcome.var = "y",
                              lead = 0:4, forbid.treatment.reversal = FALSE, 
                              use.diagonal.variance.matrix = TRUE)

msets.psm <- PM.results.psm$att

attr(msets.none, "max.match.size")
#> NULL

attr(msets.psm, "max.match.size")
#> 5

attr(msets.maha, "max.match.size")
#> 5 # <---- Correct attribute
adamrauh commented 1 year ago

Thanks for catching this! (and especially for making a PR!). We are in the process of making some updates now, so this is well timed and much appreciated. I'll work on integrating this soon.