Return 使用 mutate 和 rowwise 的列表

Return list using mutate and rowwise

我正在尝试 return 使用 mutate 和 rowwise 的列表,但出现代码中显示的错误。这些问题 Q1 Q2 有所帮助,但我想通过使用 rowwise() 遍历行来保持简单,并且这些问题已有 3 年 7 个月的历史了。谢谢

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))

您的 TestFn returns 每行有 4 个元素的列表,不能真正放在一行中;您可以先将返回的元素包装在一个向量中,以便返回的列表是单个元素列表:

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通常效率不高,如果要向量化解,可以先计算四个表达式,然后转置结果:

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

tidyverse 让您现在可以嵌套复杂的数据结构

tidyverse 解决方案

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

输出

    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]>

如何转换为data frame?

因为你的函数 returns 是一个列表,我在 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)

输出

     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