Reputation: 1692
How do I convert the list of residuals (beer_residuals
) below into a data frame?
beer <- read.csv("http://users.stat.umn.edu/~helwig/notes/MNbeer.csv")
beer_model <- lapply(unique(beer$Style),
function(x) lm(Rating~ABV, beer[beer$Style == x,]))
beer_residuals <- lapply(beer_model, resid)
I have tried the following, but neither work:
df_beer <- as.data.frame(beer_residuals)
df_beer <- do.call(rbind.data.frame, beer_residuals)
Ideally, the output would be a data frame with columns Style
and ResidualValue
as below:
Style ResidualValue
1 Lager 1.08823529
2 Lager 1.14705882
3 Lager -0.91176471
4 Lager 1.14705882
5 Lager 0.88235294
6 Lager 1.47058824
7 Lager -2.64705882
8 Lager -2.52941176
9 Lager 0.35294118
10 IPA -3.05011974
11 IPA 3.17858365
12 IPA 2.24136161
...32 more rows
I am not looking for an answer like below because the true dataset I have has 100's of grouping variables (i.e., Style
) of varying styles:
df_beer <- data.frame(matrix(ncol = 2, nrow = 44))
x <- c("Style", "ResidualValue")
colnames(df_beer) <- x
df_beer$Style <- c(rep("Lager",9),rep("IPA",17),rep("Ale",18))
df_beer$ResidualValue <- c(beer_residuals[[1]],beer_residuals[[2]],beer_residuals[[3]])
Upvotes: 3
Views: 213
Reputation: 93813
Do it with the basic lm
functionality via the formula interface directly:
lm(Rating ~ ABV:Style + Style, data = beer)$resid
Or put into a dataset:
data.frame(
beer["Style"],
Resid = lm(Rating ~ ABV:Style + Style, data = beer)$resid
)
# Style Resid
#1 Lager 1.08823529
#2 Lager 1.14705882
#3 Lager -0.91176471
#4 IPA -3.05011974
#5 Ale -0.27154460
#...
Upvotes: 2
Reputation: 388982
Using dplyr
you can follow this approach :
library(dplyr)
beer %>%
group_by(Style) %>%
summarise(model = list(lm(Rating~ABV, cur_data())),
ResidualValue = purrr::map(model, resid)) %>%
select(-model) %>%
tidyr::unnest(ResidualValue)
# Style ResidualValue
# <chr> <dbl>
# 1 Ale -0.272
# 2 Ale 0.929
# 3 Ale 1.03
# 4 Ale 3.38
# 5 Ale 2.08
# 6 Ale -6.27
# 7 Ale -0.721
# 8 Ale -1.09
# 9 Ale -2.22
#10 Ale -3.17
# … with 34 more rows
In base R, we can use by
:
do.call(rbind, by(beer, beer$Style, function(x) {
model <- lm(Rating~ABV, x)
data.frame(Style = x$Style[1], ResidualValue = resid(model))
}))
Upvotes: 4