Elasticity

The content of this vignette requires version 0.7.0 of the marginaleffects package. If that version is not yet available on CRAN, you can install it from the Github development website.

In some contexts, it is useful to interpret the results of a regression model in terms of elasticity or semi-elasticity. One strategy to achieve that is to estimate a log-log or a semilog model, where the left and/or right-hand side variables are logged. Another approach is to note that \(\frac{\partial ln(x)}{\partial x}=\frac{1}{x}\), and to post-process the marginal effects to transform them into elasticities or semi-elasticities.

For example, say we estimate a linear model of this form:

\[y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \varepsilon\]

Let \(\hat{y}\) be the adjusted prediction made by the model for some combination of covariates \(x_1\) and \(x_2\). The slope with respect to \(x_1\) (or “marginal effect”) is:

\[\frac{\partial \hat{y}}{\partial x_1}\]

We can estimate the “eyex”, “eydx”, and “dyex” (semi-)elasticities with respect to \(x_1\) as follows:

\[ \eta_1=\frac{\partial \hat{y}}{\partial x_1}\cdot \frac{x_1}{\hat{y}}\\ \eta_2=\frac{\partial \hat{y}}{\partial x_1}\cdot \frac{1}{\hat{y}} \\ \eta_3=\frac{\partial \hat{y}}{\partial x_1}\cdot x_1, \]

with interpretations roughly as follows:

  1. A percentage point increase in \(x_1\) is associated to a \(\eta_1\) percentage points increase in \(y\).
  2. A unit increase in \(x_1\) is associated to a \(\eta_2\) percentage points increase in \(y\).
  3. A percentage point increase in \(x_1\) is associated to a \(\eta_3\) units increase in \(y\).

For further intuition, consider the ratio of change in \(y\) to change in \(x\): \(\frac{\Delta y}{\Delta x}\). We can turn this ratio into a ratio between relative changes by dividing both the numerator and the denominator: \(\frac{\frac{\Delta y}{y}}{\frac{\Delta x}{x}}\). This is of course linked to the expression for the \(\eta_1\) elasticity above.

With the marginaleffects package, these quantities are easy to compute:

library(marginaleffects)
mod <- lm(mpg ~ hp + wt, data = mtcars)

marginaleffects(mod) |> summary()
#>   Term   Effect Std. Error z value   Pr(>|z|)    2.5 %   97.5 %
#> 1   hp -0.03177    0.00903  -3.519 0.00043365 -0.04947 -0.01408
#> 2   wt -3.87783    0.63273  -6.129 8.8603e-10 -5.11797 -2.63770
#> 
#> Model type:  lm 
#> Prediction type:  response

marginaleffects(mod, slope = "eyex") |> summary()
#>   Term Contrast  Effect Std. Error z value   Pr(>|z|)   2.5 %  97.5 %
#> 1   hp    eY/eX -0.2855    0.08533  -3.345 0.00082157 -0.4527 -0.1182
#> 2   wt    eY/eX -0.7464    0.14190  -5.260 1.4436e-07 -1.0245 -0.4682
#> 
#> Model type:  lm 
#> Prediction type:  response

marginaleffects(mod, slope = "eydx") |> summary()
#>   Term Contrast    Effect Std. Error z value   Pr(>|z|)     2.5 %     97.5 %
#> 1   hp    eY/dX -0.001734  0.0005007  -3.463 0.00053334 -0.002715 -0.0007528
#> 2   wt    eY/dX -0.211647  0.0378683  -5.589 2.2834e-08 -0.285868 -0.1374268
#> 
#> Model type:  lm 
#> Prediction type:  response

marginaleffects(mod, slope = "dyex") |> summary()
#>   Term Contrast  Effect Std. Error z value   Pr(>|z|)   2.5 % 97.5 %
#> 1   hp    dY/eX  -4.661      1.325  -3.519 0.00043365  -7.257 -2.065
#> 2   wt    dY/eX -12.476      2.036  -6.129 8.8603e-10 -16.466 -8.486
#> 
#> Model type:  lm 
#> Prediction type:  response