vincentarelbundock / marginaleffects

R package to compute and plot predictions, slopes, marginal means, and comparisons (contrasts, risk ratios, odds, etc.) for over 100 classes of statistical and ML models. Conduct linear and non-linear hypothesis tests, or equivalence tests. Calculate uncertainty estimates using the delta method, bootstrapping, or simulation-based inference
https://marginaleffects.com
Other
452 stars 47 forks source link

Question on elasticity computation - slope="eyex" #741

Closed CatharinaLatka closed 1 year ago

CatharinaLatka commented 1 year ago

While trying to stepwise replicate the output of slope="eyex" in the slopes-function, it seems that the derivative (slope="dydx") is multiplied with "X/predicted" rather than X/Y - is this true and what is the underlying reasoning?

also, here: https://vincentarelbundock.github.io/marginaleffects/reference/slopes.html it states '"eyex": dY/dX Y / X"' which should be '"eyex": dY/dX X / Y' or maybe even '"eyex": dY/dX * X / predicted Y', I guess?

vincentarelbundock commented 1 year ago

Yes, you're right: the Ys in that part of the document should probably have little hats.

When we call slopes() we take the derivative of the prediction equation: dYhat/dX. The elasticities are analogous. FWIW, this is also what Stata appears to do. In this file I compare output of the two programs: https://github.com/vincentarelbundock/marginaleffects/blob/main/inst/tinytest/test-elasticity.R

Did you have a specific reason to multiply by the original observation? Would that make sense for binary outcome, for example?

CatharinaLatka commented 1 year ago

Thanks for the clarification! I was just trying to figure out what is the mathematically most correct thing to do and I often read that it is suggested to multiply with X/Y..

However, the starting point was that I got negative average elasticities from the package for a linear model with fixed effects where the respective regression estimate is positive - the model does not fit the data well, original Y is cut at 0 whereas predicted Y goes into the negative sphere, which made me realize that predicted Y must be used in the elasticity formula of the package.

On the other hand, in the quasi-poisson version of this model, using "predicted" kind of solves the issue of dividing by 0 that occurs when taking the original observations.

vincentarelbundock commented 1 year ago

Cool. Glad this (kind of) makes sense.

I updated the documentation to make it clearer what is happening under the hood: 28d561031a377e

gn0 commented 1 year ago

The documentation still says "eyex": dY/dX * Y / X but I think that it should say "eyex": dY/dX * (Y / X) or "eyex": dY/dX * X / Y, as originally suggested by @CatharinaLatka. The following should be changed too:

These changes would match the definitions in R/sanitize_comparison.R:

     11     # slopes and elasticities
     12     "dydx" = function(hi, lo, eps) (hi - lo) / eps,
     13     "eyex" = function(hi, lo, eps, y, x) (hi - lo) / eps * (x / y),
     14     "eydx" = function(hi, lo, eps, y, x) ((hi - lo) / eps) / y,
     15     "dyex" = function(hi, lo, eps, x) ((hi - lo) / eps) * x,
vincentarelbundock commented 1 year ago

@gn0 what documentation are you referring to, exactly? Are you using the latest version of the package? packageVersion("marginaleffects")