我尝试使用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))
答案 0 :(得分: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
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
答案 1 :(得分: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