ngreifer / WeightIt

WeightIt: an R package for propensity score weighting
https://ngreifer.github.io/WeightIt/
102 stars 12 forks source link

ATE / ATT mixup for ebcw method #5

Closed jaredhuling closed 5 years ago

jaredhuling commented 5 years ago

See line 1043 of weightit2method.R: The following should be estimating the ATE, but ATT is specified:

ate.out <- ATE::ATE(Y = Y, Ti = treat_i, X = covs_i, ATT = TRUE, theta = A[["theta"]], verbose = TRUE, max.iter = A[["max.iter"]], tol = A[["tol"]], initial.values = A[["initial.values"]], backtrack = A[["backtrack"]], backtrack.alpha = A[["backtrack.alpha"]], backtrack.beta = A[["backtrack.beta"]])

ngreifer commented 5 years ago

It's correct as written.

Here's how ATE() works: it chooses a target population and then reweights each group to have the same means as the target population. When ATT = TRUE, it uses the treated group as the target population and reweights the control group. When ATT = FALSE, it uses the entire sample as the target population and reweight both the treated and control groups separately. This is equivalent to doing the following for each group:

  1. Append the data from one group to the original dataset
  2. Call the appended part the "control" and the original dataset the "treated"
  3. Estimate ATT weights for the combined dataset, which yield weights that reweight the "control" (the group in question) to the "treated" (the entire original dataset). The weights are the estimated weights for that group.
  4. Repeat for all treatment groups.

This is what ATE() does internally when you select ATT = FALSE. I have simply performed these actions within weightit() rather than within ATE(). If you look at the code carefully, you'll see that it performs the actions as I have listed them above. You'll get the same weights using this method as you would setting ATT = FALSE. I did it this way to make the code look more like the code I used for method = "ebal".

See below for a comparison of using ATE() with ATT = FALSE and weightit() with method = "ebcw" and esitmand = "ATE". You'll notice the weights are the same, indicating that the code as written works correctly.

data("lalonde", package = "cobalt")
library("ATE")
library("WeightIt")

ate.fit <- ATE(rep(0, 614),
               Ti = lalonde$treat,
               X = lalonde[c("age", "educ", "married", "re74")],
               ATT = FALSE)
ate.w <- ate.fit$weights.p + ate.fit$weights.q

weightit.fit <- weightit(treat ~ age + educ + married + re74,
                         data = lalonde,
                         method = "ebcw",
                         estimand = "ATE")
weightit.w <- weightit.fit$w

all.equal(ate.w, weightit.w)
#> [1] TRUE

Created on 2019-08-27 by the reprex package (v0.3.0)