lrberge / fixest

Fixed-effects estimations
https://lrberge.github.io/fixest/
377 stars 59 forks source link

Is there a way to plot a coefficients' sum? #345

Closed effedp closed 2 years ago

effedp commented 2 years ago

Hey,

As always, thank you for your excellent work.

I wondered whether there exists a way to plot through coefplot or iplot the sum of two or more coefficients with appropriate CIs.

In particular, it would be great to do it by summing two i's interactions – rather than plotting the two by i.select, finding a way to plot the coefficient-by-coefficient sum. For example, in:

example = feols(y ~ i(t, -1) + i(t, var, -1) | fe1 + fe2, data=mydata)

I would like to plot the sum of the first two coefficients for each t. Is there a built-in way to do so that I couldn't find out, or do you suggest any workaround?

Thanks!

grantmcdermott commented 2 years ago

A couple of things:

For this particular example, I think you might want to use base R's nested / interaction operator rather than i to get the full marginal effect of the t:var interactions. More details here. Something like:

mydata$t1 = factor(mydata$t)
mydata$t1 = relevel(mydata$t1, ref = "-1")

example = feols(y ~ t1 / var | fe1 + fe2, data=mydata)
coefplot(example)

But your general request is for a linear coefficient combination estimate a la the delta method. @lrberge has a manual example of how do this here. A simpler approach could just be to use @vincentarelbundock's excellent marginaleffects package. See here. The only trick is to correctly loop over your indexed t + t:var combinations and then bind into a single data frame. Something like:

# same example model as in OP
example = feols(y ~ i(t, -1) + i(t, var, -1) | fe1 + fe2, data=mydata)

library(marginaleffects)

# Single period example (here: t=1)
deltamethod(example, "`t::1` + `t::1:var` = 0") # note that we require backticks

# Multiple period example (here: assuming t runs -10:10)
lapply(-10:10, \(i) deltamethod(example, paste0("`t::", i, "` + `t::",i,":var` = 0"))) |> 
   do.call(what = "rbind")

Note that you would need to use a different plotting method on the resulting data frame rather than iplot/coefplot, since it will no longer be a fixest object. But this should be pretty easy regardless of whether you use base R plot or ggplot2.

P.S. It doesn't sound quite like you want. But fwiw ggiplot provides a convenience wrapper aggr_es for a particularly common use-case: getting the average pre- and/or post-treatment effects. You can also pass this argument to ggiplot(mod, aggr_es = "post") and it will add the aggregated line to your plot. There are examples in the README.

effedp commented 2 years ago

Thank you very much for this great answer!

grantmcdermott commented 2 years ago

Sure thing @effedp.

Please close the issue if you feel that it now has a satisfactory solution.