问题
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