我有两个不同的长度列表,并且想生成所有排列以通过R中的函数运行。我可以使用for
循环(见下文)来做到这一点,但是我不喜欢使用{{ 1}}和rbind
。我无法使其与cbind
之类的*apply
或purrr
函数一起使用,因为它们抱怨长度不相等。
最干净的tidyverse友好方法是什么?
下面的简化示例:
map2
这将生成所需的数据帧:
myfun = function(a,b){
return(a*b)
}
xvalues = c(1,2,3)
yvalues = c(10,20,30,40)
merged = c()
for (x in xvalues){
z = myfun(x,yvalues)
merged = rbind(merged,(cbind(x,yvalues,z)))
}
df = data.frame(merged)
答案 0 :(得分:2)
在要迭代所有组合的情况下,可以使用cross
系列功能,例如cross_df
来生成列表的产品集。然后,您可以像平常一样使用map
函数:
library(tidyverse)
myfun = function(a,b){
return(a*b)
}
xvalues = c(1,2,3)
yvalues = c(10,20,30,40)
cross_df(list(x = xvalues, y = yvalues)) %>%
mutate(z = map2_dbl(x, y, myfun))
#> # A tibble: 12 x 3
#> x y z
#> <dbl> <dbl> <dbl>
#> 1 1 10 10
#> 2 2 10 20
#> 3 3 10 30
#> 4 1 20 20
#> 5 2 20 40
#> 6 3 20 60
#> 7 1 30 30
#> 8 2 30 60
#> 9 3 30 90
#> 10 1 40 40
#> 11 2 40 80
#> 12 3 40 120
当然,在这种情况下,myfun
是矢量化的,因此并不需要使用map
。
cross_df(list(x = xvalues, y = yvalues)) %>%
mutate(z = myfun(x, y))
#> # A tibble: 12 x 3
#> x y z
#> <dbl> <dbl> <dbl>
#> 1 1 10 10
#> 2 2 10 20
#> 3 3 10 30
#> 4 1 20 20
#> 5 2 20 40
#> 6 3 20 60
#> 7 1 30 30
#> 8 2 30 60
#> 9 3 30 90
#> 10 1 40 40
#> 11 2 40 80
#> 12 3 40 120
由reprex package(v0.3.0)于2019-06-28创建
答案 1 :(得分:1)
有了base R
,我们可以使用expand.grid
transform(expand.grid(x= xvalues, yvalues = yvalues), z = myfun(x, yvalues))
# x yvalues z
#1 1 10 10
#2 2 10 20
#3 3 10 30
#4 1 20 20
#5 2 20 40
#6 3 20 60
#7 1 30 30
#8 2 30 60
#9 3 30 90
#10 1 40 40
#11 2 40 80
#12 3 40 120
或使用data.table
library(data.table)
CJ(x= xvalues, yvalues)[, z := myfun(x, yvalues)][]