Search code examples
rlmelasticity

Elasticity function for lm() coefficient


I wonder whether there is a function that calculates (economic) elasticity for models estimated with lm().

Elasticity for the percentage change of the dependent variable, around its mean Y, for a change of 1% in the independent variable, above its mean X, is calculated as follows: b*X/Y (b= model coefficient for the independent variable).

Below is the code for a Rmd File with a simple linear model and the elasticity of each coefficient. The output should be a table of the variable names and elasticity.

---
title: "Elasticity"
output: html_document
---

```{r}
N <- 1000
u <- rnorm(N)
x1 <- rnorm(N)
x2 <- 1 + x1 + rnorm(N)
y <- 1 + x1 + x2 + u
df <- data.frame(y,x1,x2)

fit <- lm(y ~ x1 + x2, data = df)

elax1 <- as.numeric(fit$coefficients["x1"] * mean(df$x1)/mean(df$y))
elax2 <- as.numeric(fit$coefficients["x2"] * mean(df$x2)/mean(df$y))

variable <-c ('x1','x2')
elasticity <-c (elax1,elax2)
a <- data.frame(variable,elasticity)

```

Output the results in a table:

```{r, message=FALSE,results='asis'}
require(stargazer)
stargazer(a, summary = FALSE,type = 'html',rownames=FALSE)
```

Solution

  • I came up with my own solution, maybe it can help others. Note that I have included an interaction in the model. Of course, improvements are welcome.

    ---
    title: "Elasticity"
    output: html_document
    ---
    
    Generate data and linear model:
    ```{r}
    N <- 1000
    u <- rnorm(N)
    x1 <- rnorm(N)
    x2 <- 1 + x1 + rnorm(N)
    y <- 1 + x1 + x2 + u
    df <- data.frame(y,x1,x2)
    
    fit <- lm(y ~ x1 * x2, data = df)
    
    ```
    
    
    Function to calculate elasticities:
    ```{r,results='asis'}
    
    elasticities <- function(linmod){
    Ncoef <- nrow(data.frame(linmod$coefficients))
    for(i in 2:Ncoef){
      el <- as.numeric(linmod$coefficients[i] * colMeans(model.matrix(linmod))[i]/colMeans(model.matrix(linmod))[1])
      ifelse (i== 2, elasticity <- el, elasticity <- rbind(elasticity,el))
    }
    rownames(elasticity) <- names(coef(linmod)[-1])
    colnames(elasticity) <- 'elasticities'
    
    return(data.frame(elasticity))
    }
    ```
    
    Run the elasticites function and produce a nice table:
    ```{r,results='asis',message=FALSE}
    a <- elasticities(fit)
    
    require(stargazer)
    stargazer(a, summary = FALSE, type = 'html')
    
    ```