lrberge / fixest

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

How to compute Average Partial Effects(APE)/Average Marginal Effects(AME) #397

Open jparbache opened 1 year ago

jparbache commented 1 year ago

The package has no function that allows to calculate APE and AME. When I try to use the margins::margins() function, which calculates the aforementioned values for non-linear models (such as Logit and Probit), I get an error. So what would be the best way to get these values?

rodonn commented 1 year ago

The marginaleffects package supports APE and AME for feols, feglm, fepois, and and fenegbin models. This package supports a much larger set of model types than the margins package. https://vincentarelbundock.github.io/marginaleffects/articles/supported_models.html

jparbache commented 1 year ago

Thank you @rodonn ! But I guess that, in my case, the average slopes calculated by the marginaleffects package are not the AME, since I'm working with a non-linear model. marginaleffects::avg_slopes() seems to be averaging the individual marginal effects. For Probit and Logit regressions, I believe that the AME is calculated by multiplying the estimated coefficient and the PDF... so it is a little bit more complicated than just averaging the partial derivatives. I know that the bife package does this procedure, but it is limited to only one fixed-effect, and my regressions range from 0 to 3 fixed-effects. If you are aware of any other way to obtain the AME for a Probit with multiple fixed-effects (or if I'm wrong), please let me know.

grantmcdermott commented 1 year ago

@jparbache I don't quite follow. Are you just looking to change the scale of the predictions? If so, then that simply requires an appropriate type = "link" argument and works exactly the same for both packages... notwithstanding the fact the marginaleffects supersedes margins in many other ways.

library(margins)
library(marginaleffects)
library(fixest)

x  =   glm(am ~ cyl + hp * wt, data = mtcars, family = binomial)
#> Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
x2 = feglm(am ~ cyl + hp * wt, data = mtcars, family = binomial)

# AME (implict type = "response")
summary(margins(x))
#>  factor     AME     SE       z      p   lower  upper
#>     cyl  0.0216 0.0493  0.4377 0.6616 -0.0750 0.1181
#>      hp  0.0027 0.0023  1.1596 0.2462 -0.0018 0.0072
#>      wt -0.5158 0.2685 -1.9209 0.0547 -1.0421 0.0105

# summary(slopes(x)) # same as next line
avg_slopes(x)
#> 
#>  Term Estimate Std. Error      z Pr(>|z|)    2.5 %  97.5 %
#>   cyl  0.02156    0.04923  0.438   0.6614 -0.07493 0.11806
#>   hp   0.00267    0.00229  1.164   0.2444 -0.00182 0.00716
#>   wt  -0.51585    0.26534 -1.944   0.0519 -1.03592 0.00421
#> 
#> Columns: term, estimate, std.error, statistic, p.value, conf.low, conf.high

# APE
summary(margins(x, type = "link"))
#>  factor      AME     SE       z      p    lower  upper
#>     cyl   0.5156 1.1695  0.4409 0.6593  -1.7765 2.8077
#>      hp   0.0515 0.0357  1.4429 0.1490  -0.0185 0.1215
#>      wt -12.2426 7.6784 -1.5944 0.1108 -27.2920 2.8067

# summary(slopes(x, type = "link")) # same as next line
avg_slopes(x, type = "link")
#> 
#>  Term Estimate Std. Error      z Pr(>|z|)    2.5 % 97.5 %
#>   cyl   0.5156     1.1695  0.441    0.659  -1.7764  2.808
#>   hp    0.0515     0.0357  1.443    0.149  -0.0185  0.121
#>   wt  -12.2426     7.6784 -1.594    0.111 -27.2920  2.807
#> 
#> Columns: term, estimate, std.error, statistic, p.value, conf.low, conf.high

# Just to prove that fixest objects work too...
avg_slopes(x2, type = "link")
#> 
#>  Term Estimate Std. Error      z Pr(>|z|)    2.5 % 97.5 %
#>   cyl   0.5156     1.2531  0.411    0.681  -1.9404  2.972
#>   hp    0.0515     0.0383  1.347    0.178  -0.0235  0.126
#>   wt  -12.2426     8.2275 -1.488    0.137 -28.3683  3.883
#> 
#> Columns: term, estimate, std.error, statistic, p.value, conf.low, conf.high

Created on 2023-03-08 with reprex v2.0.2

This is all covered in the excellent and extensive marginaleffects documentation (e.g., here). You would probably benefit from taking a look through these, but I think this issue can be closed now.