Code
Suppose I have a tibble
which contains both atomic vectors and objects:
library(dplyr)
set.seed(1)
(mdat <- data_frame(n = 2:5, mod = rep(list(lm(rnorm(10) ~ 1)), 4)))
# # A tibble: 4 × 2
# n mod
# <int> <list>
# 1 2 <S3: lm>
# 2 3 <S3: lm>
# 3 4 <S3: lm>
# 4 5 <S3: lm>
Now I want to use do
to create a new data.frame
:
ndat <- mdat %>% rowwise() %>% do(data.frame(mod2 = I(list(lm(rnorm(.$n) ~ 1)))))
Question
If I want to keep the original columns I see 2 possibilities:
Add the columns explicitly in the
do
call:(mdat %>% rowwise() %>% do(data.frame(n = .$n, mod = I(list(.$mod)), mod2 = I(list(lm(rnorm(.$n) ~ 1)))))) # Source: local data frame [4 x 3] # Groups: <by row> # # A tibble: 4 × 3 # n mod mod2 # * <int> <list> <list> # 1 2 <S3: lm> <S3: lm> # 2 3 <S3: lm> <S3: lm> # 3 4 <S3: lm> <S3: lm> # 4 5 <S3: lm> <S3: lm>
Add an artificial
id
column and join the data frames (output stripped):left_join(mdat %>% mutate(id = 1:4), ndat %>% ungroup() %>% mutate(id = 1:4), by = "id")
Option 1 is error prone, because I have to hard-code all columns of mdat
. Option 2 introduces a meaningless id
column.
My question is: can I achieve the desired output directly via do
? My first thought was to use
mdat %>% rowwise() %>% do(data.frame(., mod2 = I(list(lm(rnorm(.$n) ~ 1)))))
But this does not work because of column mod
:
# Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
# cannot coerce class ""lm"" to a data.frame
So do I have to rely on option 2, or is there a better way (better in the sense of avoiding additional columns and hard-coding columns)?