更好地结合" R中多个列表的多元素索引的所有组合?

时间:2017-07-21 03:40:34

标签: r list for-loop apply mapply

假设我有两个列表,每个列表包含多个索引中多个子元素的可变数量:

list.a <- list(c("a","b","c"), c("x", "y", "z"))
list.b <- list(c("d", "e", "f","g"), c("m", "n"))
  • 这导致:

    > list.a
    [[1]]
    [1] "a" "b" "c"
    
    [[2]]
    [1] "x" "y" "z"
    

    > list.b
    [[1]]
    [1] "d" "e" "f" "g" "h"
    
    [[2]]
    [1] "m" "n" 
    

如何递归访问每个列表中相应索引的每个组合子元素?

  • 例如,我想访问第一个索引和xm,xn,ym,yn,zm和zn的ad,ae,af,ag,bd,be,...等组合从每个列表的第二个索引。

    [[1]]
     [1] "a d" "a e" "a f" "a g" "b d" "b e" "b f" "b g" "c d" "c e" "c f" "c g"
    
    [[2]]
    [1] "x m" "x n" "y m" "y n" "z m" "z n"
    
当我从每个列表中有多个子元素时,

mapply似乎不起作用(特别是如果两个列表中的元素数量不相等):

> mapply(paste,list.a,list.b)
[[1]]
[1] "a d" "b e" "c f" "a g"

[[2]]
[1] "x m" "y n" "z m"
  • 它会跳过一半的组合,而只是回收两个列表中较短的一个。我希望它能够在两个列表的共享索引中组合所有组合。

我知道我也可以使用for循环......:

list.d <- list()
for(i in 1:length(list.a)) {
  list.c <- list()
  list.d[[i]] <- {
    for(j in list.a[[i]]) {
      for(k in list.b[[i]]) {
       list.c <- c(list.c, paste(j, k))
      }
    }
    unlist(list.c)
    }
}

产生所需的结果:

> list.d
[[1]]
 [1] "a d" "a e" "a f" "a g" "b d" "b e" "b f" "b g" "c d" "c e" "c f" "c g"

[[2]]
[1] "x m" "x n" "y m" "y n" "z m" "z n"

...但是这个循环充其量是凌乱的,而且对于庞大的列表来说变得相当慢。

有更好的方法吗?

  • 具体来说,使用apply函数是否有特殊功能或某种方法可以更有效地完成此任务?

&LT;申请&gt;

(这部分不是回答问题,而是提供其使用的背景/扩展):

对于那些好奇的人,我想将其扩展到paste()之外,而是想在data.frame上使用它。

  • 例如:

    假设我有两个列表,每个列表包含多个具有多个子元素的索引:

    l1 <- list(c(1933:1935),c(1950:1954), c(2012:2013))  #groups of years
    l2 <- list(c(19:21),c(19:24),c(22:26))               #groups of plot numbers
    

    我们还假设我有以下data.frame:

    dat <- data.frame(plot = rep(1:30,81), year = rep(1933:2013, each = 30), area = sample(270))
    
    > head(dat)
      plot year area
    1    1 1933  137
    2    2 1933   72
    3    3 1933  136
    4    4 1933  187
    5    5 1933  206
    6    6 1933   74
    

    我想创建一个新列表(我们称之为l3),其中包含l1(年)和l2的所有组合的总和区域(图)对于每个重合列表索引。

    • 例如,结果列表的[[1]]的结果将是1933年,1934年<19>的每个地块的总和,20 &amp; 21 < em>&amp; 1935年。

      [[2]]的结果将是1950年至1954年每年19至24年的总面积。

1 个答案:

答案 0 :(得分:1)

您需要expand.grid,用于:

  

从提供的矢量的所有组合创建数据框   因素。

使用do.call(paste, ...)将数据框的所有列粘贴在一起。

Map(function(a,b) do.call(paste, expand.grid(a,b)), list.a, list.b)

#[[1]]
# [1] "a d" "b d" "c d" "a e" "b e" "c e" "a f" "b f" "c f" "a g" "b g" "c g"

#[[2]]
#[1] "x m" "y m" "z m" "x n" "y n" "z n"

对于问题的第二部分,我们可以逐年对数据框进行子集化并首先绘制图,然后使用 rowsum area 汇总到 >:

Map(function(years, plots) {
    with(subset(dat, plot %in% plots & year %in% years), rowsum(area, year))
}, l1, l2)

[[1]]
     [,1]
1933  257
1934  398
1935  640

[[2]]
     [,1]
1950  950
1951  457
1952  601
1953 1202
1954 1148

[[3]]
     [,1]
2012  736
2013  497