0

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:

  1. 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>
    
  2. 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)?

thothal
  • 16,690
  • 3
  • 36
  • 71

0 Answers0