margins icon indicating copy to clipboard operation
margins copied to clipboard

Feature request: fixest support

Open karldw opened this issue 6 years ago • 6 comments
trafficstars

The fixest package is a new-ish package for estimating OLS and GLM models with fixed effects. It would be lovely if margins supported it. There are already predict and vcov methods, which should make things easier for anyone who wants to take this up.

Ref: https://github.com/leeper/margins/issues/101, https://github.com/sgaure/lfe/issues/13 CC @grantmcdermott


Please specify whether your issue is about:

  • [ ] a possible bug
  • [ ] a question about package functionality
  • [x] a suggested code or documentation change, improvement to the code, or feature request

Put your code here:

library(margins)
library(fixest)

x <- fixest::feols(mpg ~ hp * wt | cyl, data = mtcars)
margins(x)
#> Error in terms.default(model): no terms component nor attribute

head(predict(x))
#> [1] 22.47196 21.28068 25.94454 19.69230 17.08487 18.65003
vcov(x)
#>                  hp            wt         hp:wt
#> hp     1.641964e-04  0.0042546536 -2.454378e-05
#> wt     4.254654e-03  0.1706445284 -8.152661e-04
#> hp:wt -2.454378e-05 -0.0008152661  4.200967e-06
#> attr(,"type")
#> [1] "Clustered (cyl)"

Created on by the reprex package (v0.3.0)

Note that by default, fixest clusters by the fixed effects, and different clustering can be specified as arguments to summary or vcov. I'm not sure what approach margins wants to take here.

karldw avatar Nov 08 '19 05:11 karldw

Ha, I was just tweeting about this package yesterday. It looks fantastic. I didn't realise it had a predict method, though. Even more good news.

grantmcdermott avatar Nov 08 '19 20:11 grantmcdermott

Thanks, I'll look into this.

leeper avatar Dec 22 '19 09:12 leeper

It looks reasonably easy to add support in the prediction package, though the fixest predict method does not appear to support an argument like se.fit (as in predict.lm for example).

See my branch of the prediction package below.

The other challenge is that the default find_terms method doesn't work on these objects. I'm sure there's a relatively easy workaround.

Do you all think there is serious interest in this package? Is it worth the time?

remotes::install_github('vincentarelbundock/prediction@fixest')

library(fixest)
library(margins)
library(prediction)

mod <- feols(mpg ~ hp * wt | cyl, data = mtcars)
head(prediction(mod))
#>    mpg cyl disp  hp drat    wt  qsec vs am gear carb   fitted se.fitted
#> 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 22.47196        NA
#> 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 21.28068        NA
#> 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 25.94454        NA
#> 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 19.69230        NA
#> 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 17.08487        NA
#> 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 18.65003        NA

Created on 2020-05-29 by the reprex package (v0.3.0)

vincentarelbundock avatar May 29 '20 18:05 vincentarelbundock

Nice @vincentarelbundock.

Do you all think there is serious interest in this package? Is it worth the time?

I can't speak to the effort involved, especially since I personally don't have time atm to commit to this. But I will say that fixest is fantastic IMO. Very flexible and insanely fast. It's honestly one of my favourite modeling packages.

FWIW a number of margin's already-supported model classes don't provide se.fit arguments. This was also something we discussed at equivalent lfe issue (referenced in @karldw's original post above). Getting predictive SEs for fixed-effect estimators like these is likely impossible without bootstrapping everything.

PS — I'm sure everyone on this thread knows this, but for interactions containing a minimum of one categorical variable we can at least use the x1 / x2 specification trick to obtain the full marginal effects directly in the model object (see here).

grantmcdermott avatar May 30 '20 00:05 grantmcdermott

I looked into this a bit, @karldw, and it looks pretty easy to add fixest support. I saved a proof of concept to this Gist:

https://gist.github.com/vincentarelbundock/868556e242af647b1e6e74998a1c6364

I've only tried it with a simple linear model with one interaction, but it seems to work. You can play with it by running this code:

library(fixest)
library(margins)
library(prediction)

# Load new methods to add support for `fixest` objects
url <- 'https://gist.githubusercontent.com/vincentarelbundock/868556e242af647b1e6e74998a1c6364/raw/004296df1d7f9a4d314b416cc46796d764a09b71/margins.fixest.R'
source(url)

# Download data and fit model
url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/plm/EmplUK.csv'
dat <- read.csv(url)
dat$capital <- as.logical(dat$capital < median(dat$capital))
mod <- feols(wage ~ emp * capital | firm + year, dat)

# strategy 1: margins
mfx <- margins(mod, at = list('capital' = c(TRUE, FALSE)))
mfx <- data.frame(summary(mfx))
mfx[mfx$factor == 'emp',]
#>   factor capital         AME SE  z  p lower upper
#> 3    emp   FALSE -0.04627018 NA NA NA    NA    NA
#> 4    emp    TRUE  0.14303633 NA NA NA    NA    NA

# strategy 2: grant's trick
tmp <- feols(wage ~ capital / emp | firm + year, dat) 
coef(tmp)[2:3]
#> capitalFALSE:emp  capitalTRUE:emp 
#>      -0.04627018       0.14303633

Created on 2020-05-30 by the reprex package (v0.3.0)

If @leeper is interested, I can push this the last mile by making separate PRs for the prediction and the margins packages.

@grantmcdermott I wasn't aware of that neat trick with / in the formula. Very cool. Thanks for posting the blog! FYI, I opened a PR to add glance and tidy methods to fixest. Those are already on modelsummary's latest Github, so you can make tables that will automatically detect and display which fixed effects are included. Example here: https://github.com/lrberge/fixest/issues/21

vincentarelbundock avatar May 30 '20 19:05 vincentarelbundock

Still interested in this in 2021

IsadoraBM avatar Aug 17 '21 14:08 IsadoraBM

Still interested in this in 2021

Still interested in 2022

mikenguyen13 avatar Oct 26 '22 02:10 mikenguyen13

This package has been supplanted by the marginaleffects package. https://vincentarelbundock.github.io/marginaleffects/

Among other improvements (faster,. more features) it supports fixest objects.

@karldw I think we can close, since this package appears to be in stasis and there's a good, alternative solution.

grantmcdermott avatar Oct 26 '22 05:10 grantmcdermott