我有两个不同长度的列表,并且想生成所有排列以运行 R 中的函数。我可以使用 for
循环来实现(见下文),但我不喜欢使用 rbind 和 cbind。我无法让它与 *apply
或 purrr
函数(如 map2
)一起使用,因为它们提示长度不等。
最干净、tidyverse 友好的方法是什么?
下面的简化示例:
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)
这会生成所需的数据帧:
x yvalues z
1 1 10 10
2 1 20 20
3 1 30 30
4 1 40 40
5 2 10 20
6 2 20 40
7 2 30 60
8 2 40 80
9 3 10 30
10 3 20 60
11 3 30 90
12 3 40 120
最佳答案
在您想要迭代所有组合的情况下,您可以使用 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于2019-06-28创建(v0.3.0)
关于r - 在 R 中映射/迭代不同大小的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56811032/