Return list using mutate and rowwise

橙三吉。 提交于 2019-12-22 18:42:39

问题


I'm trying to return a list using mutate and rowwise but get the error shown in the code. These questions Q1 Q2 helped, but I'd like to keep it simple by iterating over rows using rowwise(), and the questions are 3yr 7mth old. Thanks.

library(tidyverse)    
df <-  data.frame(Name=c("a","a","b","b","c"),X=c(1,2,3,4,5), Y=c(2,3,4,2,2))

    TestFn <- function(X,Y){
      Z <- list(X*5,Y/2,X+Y,X*2+5*Y)
      return (Z)
    }

    #this works
    SingleResult <- TestFn(5,20)

    #error - Error in mutate_impl(.data, dots) : incompatible size (4), expecting 1 (the group size) or 1
    dfResult <- df %>% 
      rowwise() %>% 
      mutate(R=TestFn(X,Y))

回答1:


Your TestFn returns a 4 elements list per row, which can't really be fit in a row; You can wrap the returned elements in a vector first so the returned list is a single element list:

TestFn <- function(X, Y) list(c(X*5, Y/2, X+Y, X*2+5*Y))
#                             ^ 
df %>% rowwise() %>% mutate(R=TestFn(X,Y)) %>% pull(R)
#[[1]]
#[1]  5  1  3 12

#[[2]]
#[1] 10.0  1.5  5.0 19.0

#[[3]]
#[1] 15  2  7 26

#[[4]]
#[1] 20  1  6 18

#[[5]]
#[1] 25  1  7 20

rowwise is usually not as efficient, if you want to vectorize the solution, you can calculate the four expressions firstly and then transpose the result:

df$R = with(df, data.table::transpose(list(X*5, Y/2, X+Y, X*2+5*Y)))
df
#  Name X Y                    R
#1    a 1 2          5, 1, 3, 12
#2    a 2 3 10.0, 1.5, 5.0, 19.0
#3    b 3 4         15, 2, 7, 26
#4    b 4 2         20, 1, 6, 18
#5    c 5 2         25, 1, 7, 20



回答2:


tidyverse lets you nest complicated data structures now

tidyverse solution

df %>%
  mutate(copyX = X, copyY = Y) %>%
  nest(copyX, copyY) %>%
  mutate(data = map(data, ~TestFn(.x$copyX, .x$copyY)))

output

    Name     X     Y       data
  <fctr> <dbl> <dbl>     <list>
1      a     1     2 <list [4]>
2      a     2     3 <list [4]>
3      b     3     4 <list [4]>
4      b     4     2 <list [4]>
5      c     5     2 <list [4]>

How to convert to data frame?

Since your function returns a list, I added an additional step before unnesting

df %>%
  mutate(copyX = X, copyY = Y) %>%
  nest(copyX, copyY) %>%
  mutate(data = map(data, ~TestFn(.x$copyX, .x$copyY))) %>%
  mutate(data = map(data, ~unlist(.x))) %>%
  unnest(data)

output

     Name     X     Y  data
   <fctr> <dbl> <dbl> <dbl>
 1      a     1     2   5.0
 2      a     1     2   1.0
 3      a     1     2   3.0
 4      a     1     2  12.0
 5      a     2     3  10.0
 6      a     2     3   1.5
 # etc


来源:https://stackoverflow.com/questions/46106423/return-list-using-mutate-and-rowwise

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!