18  Elasticity

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 ln(x)x=1x, 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=β0+β1x1+β2x2+ε

Let y^ be the adjusted prediction made by the model for some combination of covariates x1 and x2. The slope with respect to x1 (or “marginal effect”) is:

y^x1

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

η1=y^x1x1y^ η2=y^x11y^ η3=y^x1x1

with interpretations roughly as follows:

  1. A percentage point increase in x1 is associated to a η1 percentage points increase in y.
  2. A unit increase in x1 is associated to a η2 percentage points increase in y.
  3. A percentage point increase in x1 is associated to a η3 units increase in y.

For further intuition, consider the ratio of change in y to change in x: ΔyΔx. We can turn this ratio into a ratio between relative changes by dividing both the numerator and the denominator: ΔyyΔxx. This is of course linked to the expression for the η1 elasticity above.

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

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

avg_slopes(mod)
#> 
#>  Term Estimate Std. Error     z Pr(>|z|)    S   2.5 %  97.5 %
#>    hp  -0.0318    0.00903 -3.52   <0.001 11.2 -0.0495 -0.0141
#>    wt  -3.8778    0.63273 -6.13   <0.001 30.1 -5.1180 -2.6377
#> 
#> Type:  response 
#> Comparison: dY/dX

avg_slopes(mod, slope = "eyex")
#> 
#>  Term Estimate Std. Error     z Pr(>|z|)    S  2.5 % 97.5 %
#>    hp   -0.285     0.0855 -3.34   <0.001 10.2 -0.453 -0.118
#>    wt   -0.746     0.1418 -5.26   <0.001 22.7 -1.024 -0.468
#> 
#> Type:  response 
#> Comparison: eY/eX

avg_slopes(mod, slope = "eydx")
#> 
#>  Term Estimate Std. Error     z Pr(>|z|)    S    2.5 %    97.5 %
#>    hp -0.00173   0.000502 -3.46   <0.001 10.8 -0.00272 -0.000751
#>    wt -0.21165   0.037849 -5.59   <0.001 25.4 -0.28583 -0.137464
#> 
#> Type:  response 
#> Comparison: eY/dX

avg_slopes(mod, slope = "dyex")
#> 
#>  Term Estimate Std. Error     z Pr(>|z|)    S  2.5 % 97.5 %
#>    hp    -4.66       1.32 -3.52   <0.001 11.2  -7.26  -2.06
#>    wt   -12.48       2.04 -6.13   <0.001 30.1 -16.47  -8.49
#> 
#> Type:  response 
#> Comparison: dY/eX