rfixest

multiple rhs fixest estimations


I am analyzing three experiments that ran simultaneously, like so:

df <- tibble(
  treatment_1 = 1 * rbinom(1000, 1, 0.5),
  treatment_2 = 2 * rbinom(1000, 1, 0.5),
  treatment_3 = 3 * rbinom(1000, 1, 0.5),
  covariate = rnorm(1000),
  y = covariate + treatment_1 + treatment_2 + treatment_3 + rnorm(1000),
  cluster = rep(1:10, each = 100),
)

What I would like to estimate for each of the experiments is the specification y ~ covariate + treatment_i + i(treatment_i, covariate, ref = 0) | cluster, which of course I can do by just running feols() thrice:

fixest::feols(fml = y ~ covariate + treatment_1 + i(treatment_1, covariate, ref = 0) | cluster, data = df)
fixest::feols(fml = y ~ covariate + treatment_2 + i(treatment_2, covariate, ref = 0) | cluster, data = df)
fixest::feols(fml = y ~ covariate + treatment_3 + i(treatment_3, covariate, ref = 0) | cluster, data = df)

This seems a little inefficient though as this requires I compute the cluster fixed effects three times. Is there a way to estimate these three specifications using fixest's multiple estimations functionality?


Solution

  • Yes, as explained in the documentation under "Multiple RHS":

    sw: this function is replaced sequentially by each of its arguments. For example, y ~ x1 + sw(x2, x3) leads to two estimations: y ~ x1 + x2 and y ~ x1 + x3.

    In your case this becomes:

    fixest::feols(y ~ covariate +
                      sw(treatment_1 + i(treatment_1, covariate, ref = 0),
                         treatment_2 + i(treatment_2, covariate, ref = 0),
                         treatment_3 + i(treatment_3, covariate, ref = 0)) | cluster, data=df)
    

    As a postscript, I've been wondering if you can condense this further, for example by using a wrapper that just specifies the treatment index & automatically adds the necessary covariate/interaction. The answer seems to be 'no', at least not easily.

    The fixest stepwise functions work on a (very lazily evaluated) match.call, are only recognized by their already-defined names, and the fitting routine/sanity checks extract the provided arguments, not just the returned (character) formulae, in other places leading to mismatches even if you were to redefine them. In summary, the formula pretty much has to be provided verbatim to sw.