2

我正在尝试使用 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))
4

2 回答 2

3

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

如何转换为数据框?

unnest由于您的函数返回一个列表,因此我在ing之前添加了一个附加步骤

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
于 2017-09-07T23:42:41.560 回答
2

TestFn每行返回一个 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
于 2017-09-07T23:27:09.010 回答