使用dplyr将预测值列添加到数据框

时间:2015-09-25 02:00:14

标签: r dplyr

我有一个带有一列模型的数据框,我正在尝试添加一列预测值。一个最小的例子是:

exampleTable <- data.frame(x = c(1:5, 1:5),
                           y = c((1:5) + rnorm(5), 2*(5:1)),
                           groups = rep(LETTERS[1:2], each = 5))

models <- exampleTable %>% group_by(groups) %>% do(model = lm(y ~ x, data = .))
exampleTable <- left_join(tbl_df(exampleTable), models)

estimates <- exampleTable %>% rowwise() %>% do(Est = predict(.$model, newdata = .["x"]))

如何向exampleTable添加一列数字预测?我尝试使用mutate直接将列添加到表中但没有成功。

> exampleTable <- exampleTable %>% rowwise() %>% mutate(data.frame(Pred = predict(.$model, newdata = .["x"])))
Error: no applicable method for 'predict' applied to an object of class "list"

现在我使用bind_colsestimates添加到exampleTable,但我正在寻找更好的解决方案。

estimates <- exampleTable %>% rowwise() %>% do(data.frame(Pred = predict(.$model, newdata = .["x"])))
exampleTable <- bind_cols(exampleTable, estimates)

如何一步完成?

4 个答案:

答案 0 :(得分:7)

使用建模器,可以使用tidyverse解决方案。

输入

library(dplyr)
library(purrr)
library(tidyr)

# generate the inputs like in the question
example_table <- data.frame(x = c(1:5, 1:5),
                            y = c((1:5) + rnorm(5), 2*(5:1)),
                            groups = rep(LETTERS[1:2], each = 5))

models <- example_table %>% 
  group_by(groups) %>% 
  do(model = lm(y ~ x, data = .)) %>%
  ungroup()
example_table <- left_join(tbl_df(example_table ), models, by = "groups")

解决方案

# generate the extra column
example_table %>%
  group_by(groups) %>%
  do(modelr::add_predictions(., first(.$model)))

说明

add_predictions使用给定模型将新列添加到数据框。不幸的是,它仅采用一个模型作为参数。认识do。使用do,我们可以在每个组上单独运行add_prediction

.代表分组的数据帧,.$model代表模型列,first()代表每组的第一个模型。

简体

只有一个模型,add_predictions效果很好。

# take one of the models
model <- example_table$model[[6]]

# generate the extra column
example_table %>%
  modelr::add_predictions(model)

食谱

如今,tidyverse已从modelr软件包转移到recipes,因此一旦该软件包成熟,这可能就是新的选择。

答案 1 :(得分:3)

为了记录,这在data.table

中是无痛的
library(data.table)
setDT(exampleTable)

# actually, the more typical usage is to set the newdata
#   argument here to .SD (especially for multivariate regressions; see:
#   https://stackoverflow.com/a/32277135/3576984
exampleTable[ , estimates := predict(lm(y ~ x), data.frame(x)), by = groups]

exampleTable
#     x          y groups  estimates
#  1: 1  0.3123549      A  0.6826629
#  2: 2  2.7636593      A  1.8297796
#  3: 3  1.7771181      A  2.9768963
#  4: 4  5.2031623      A  4.1240130
#  5: 5  4.8281869      A  5.2711297
#  6: 1 10.0000000      B 10.0000000
#  7: 2  8.0000000      B  8.0000000
#  8: 3  6.0000000      B  6.0000000
#  9: 4  4.0000000      B  4.0000000
# 10: 5  2.0000000      B  2.0000000

如果您按照data.table的清晰度进行销售,请查看intro vignettes

另外,您并非真的需要按groups进行分组。只需将其作为虚拟交互。如果我记得,无论如何,这是获得正确标准错误的正确方法:

exampleTable[ , estimates2 := predict(lm(y ~ x * factor(groups)), .SD)]
exampleTable[ , all.equal(estimates, estimates2)]
# [1] TRUE

答案 2 :(得分:3)

使用tidyverse:

library(dplyr)
library(purrr)
library(tidyr)
library(broom)

exampleTable <- data.frame(
  x = c(1:5, 1:5),
  y = c((1:5) + rnorm(5), 2*(5:1)),
  groups = rep(LETTERS[1:2], each = 5)
)

exampleTable %>% 
  group_by(groups) %>%
  nest() %>% 
  mutate(model = data %>% map(~lm(y ~ x, data = .))) %>% 
  mutate(Pred = map2(model, data, predict)) %>% 
  unnest(Pred, data)

# A tibble: 10 × 4
   groups      Pred     x          y
   <fctr>     <dbl> <int>      <dbl>
1       A  1.284185     1  0.9305908
2       A  1.909262     2  1.9598293
3       A  2.534339     3  3.2812002
4       A  3.159415     4  2.9283637
5       A  3.784492     5  3.5717085
6       B 10.000000     1 10.0000000
7       B  8.000000     2  8.0000000
8       B  6.000000     3  6.0000000
9       B  4.000000     4  4.0000000
10      B  2.000000     5  2.0000000

答案 3 :(得分:1)

呃,这只是稍好一点:

answer = 
  exampleTable %>%
  group_by(groups) %>%
  do(lm( y ~ x , data = .) %>% 
       predict %>% 
       data_frame(prediction = .)) %>%
  bind_cols(exampleTable)

我希望这会奏效,但它没有。

answer = 
  exampleTable %>%
  group_by(groups) %>%
  mutate(prediction = 
           lm( y ~ x , data = .) %>% 
           predict)