Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

save residuals with `dplyr`

Tags:

r

dplyr

I want to use dplyr to group a data.frame, fit linear regressions and save the residuals as a column in the original, ungrouped data.frame.

Here's an example

> iris %>%
   select(Sepal.Length, Sepal.Width) %>%
   group_by(Species) %>%
   do(mod = lm(Sepal.Length ~ Sepal.Width, data=.)) %>%

Returns:

     Species     mod
1     setosa <S3:lm>
2 versicolor <S3:lm>
3  virginica <S3:lm>

Instead, I would like the original data.frame with a new column containing residuals.

For example,

    Sepal.Length Sepal.Width  resid
1   5.1         3.5  0.04428474
2   4.9         3.0  0.18952960
3   4.7         3.2 -0.14856834
4   4.6         3.1 -0.17951937
5   5.0         3.6 -0.12476423
6   5.4         3.9  0.06808885
like image 432
Austin Richardson Avatar asked Dec 12 '14 21:12

Austin Richardson


People also ask

How do I save residuals in R?

Go to the object inspector > Inputs > SAVE VARIABLES > Residuals, or go to Anything > Advanced Analysis > Regression > Save Variables(s) > Residuals.

How do I add residuals to a dataset in R?

First of all, create a data frame. Then, use lm function to create the regression model and find the residuals using resid function and adding them to the data frame with $ operator.

What is a residual in stats?

Definition. The residual for each observation is the difference between predicted values of y (dependent variable) and observed values of y . Residual=actual y value−predicted y value,ri=yi−^yi.


2 Answers

I adapted an example from http://jimhester.github.io/plyrToDplyr/.

r <- iris %>%
  group_by(Species) %>%
  do(model = lm(Sepal.Length ~ Sepal.Width, data=.)) %>%
  do((function(mod) {
     data.frame(resid = residuals(mod$model))
  })(.))

corrected <- cbind(iris, r)

update Another method is to use the augment function in the broom package:

r <- iris %>%
  group_by(Species) %>%
  do(augment(lm(Sepal.Length ~ Sepal.Width, data=.))

Which returns:

Source: local data frame [150 x 10]
Groups: Species

   Species Sepal.Length Sepal.Width  .fitted    .se.fit      .resid       .hat
1   setosa          5.1         3.5 5.055715 0.03435031  0.04428474 0.02073628
2   setosa          4.9         3.0 4.710470 0.05117134  0.18952960 0.04601750
3   setosa          4.7         3.2 4.848568 0.03947370 -0.14856834 0.02738325
4   setosa          4.6         3.1 4.779519 0.04480537 -0.17951937 0.03528008
5   setosa          5.0         3.6 5.124764 0.03710984 -0.12476423 0.02420180
...
like image 102
Austin Richardson Avatar answered Sep 18 '22 23:09

Austin Richardson


A solution that seems to be easier than the ones proposed so far and closer to the code of the original question is :

iris %>%
   group_by(Species) %>%
   do(data.frame(., resid = residuals(lm(Sepal.Length ~ Sepal.Width, data=.))))

Result :

# A tibble: 150 x 6
# Groups:   Species [3]
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   resid
          <dbl>       <dbl>        <dbl>       <dbl> <fct>     <dbl>
 1          5.1         3.5          1.4         0.2 setosa   0.0443
 2          4.9         3            1.4         0.2 setosa   0.190 
 3          4.7         3.2          1.3         0.2 setosa  -0.149 
 4          4.6         3.1          1.5         0.2 setosa  -0.180 
 5          5           3.6          1.4         0.2 setosa  -0.125 
 6          5.4         3.9          1.7         0.4 setosa   0.0681
 7          4.6         3.4          1.4         0.3 setosa  -0.387 
 8          5           3.4          1.5         0.2 setosa   0.0133
 9          4.4         2.9          1.4         0.2 setosa  -0.241 
10          4.9         3.1          1.5         0.1 setosa   0.120 
like image 45
Gilles Avatar answered Sep 20 '22 23:09

Gilles