【问题标题】:Mapping / iterating over different sized lists in R映射/迭代R中不同大小的列表
【发布时间】:2019-11-10 15:44:31
【问题描述】:

我有两个不同长度的列表,并希望生成所有排列以通过 R 中的函数运行。我可以使用 for 循环(见下文)但我不喜欢使用 rbindcbind。我无法让它与*applypurrr 之类的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

【问题讨论】:

    标签: r loops tidyverse


    【解决方案1】:

    您可以使用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 年 6 月 28 日创建

    【讨论】:

      【解决方案2】:

      使用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)][]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-28
        • 1970-01-01
        • 2015-02-11
        • 1970-01-01
        • 2016-08-02
        相关资源
        最近更新 更多