【问题标题】:Paste a list to a vector, repeating the list for each vector level将列表粘贴到向量,为每个向量级别重复列表
【发布时间】:2018-03-10 21:36:23
【问题描述】:

我想完成以下任务,而不必进入 for 循环,而是在单个 apply() 命令中。

我有一个列表a,我想重复N 次,其中N 是向量b 的长度,将a 的每个重复粘贴到b 的元素中。

到目前为止,我已经完成了以下 MWE:

var <- paste("var", 1:4, sep="")
treat <- c("A","B")
spec <- paste("sp", 1:3, sep="")
a <- combn(var, 2, simplify = FALSE)#this 6 times, for each treatment and species
b <- do.call(paste, c(expand.grid(treat, spec), sep='.'))
a1 <- lapply(a, paste, b[1], sep='.')
a2 <- lapply(a, paste, b[2], sep='.')
a3 <- lapply(a, paste, b[3], sep='.')
a4 <- lapply(a, paste, b[4], sep='.')
a5 <- lapply(a, paste, b[5], sep='.')
a6 <- lapply(a, paste, b[6], sep='.')
a.final <- c(a1,a2,a3,a4,a5,a6)
a.final

如果我可以在a 之前粘贴b,那将是最佳选择。

请注意,我的出发点是 3 个向量:var、treat 和 spec,因此您可以随意更改任何内容。

【问题讨论】:

    标签: r list combinations apply paste


    【解决方案1】:

    选项 1: 我们可以在没有任何 apply() 循环的情况下完成此操作。让我们 unlist() a 列表,paste() 它复制到 b 值,然后 relist() 它基于复制的 a 列表。试试这个:

    aa <- relist(
        paste(unlist(a), rep(b, each=sum(lengths(a))), sep="."), 
        rep.int(a, length(b))
    )
    

    检查:

    identical(aa, a.final)
    # [1] TRUE
    

    选项 1 和 a 之前的 b: 现在,要将 b 值放在前面,只需交换 paste() 调用中的参数:

    relist(
        paste(rep(b, each=sum(lengths(a))), unlist(a), sep = "."),  
        rep.int(a, length(b))
    )
    

    选项 2: 此选项使用 apply() 循环。这里我们使用Map()进行一对一粘贴。

    ra <- rep(a, length(b))
    aa2 <- Map(paste, ra, relist(rep(b, each=sum(lengths(a))), ra), sep = ".")
    

    检查:

    identical(aa2, a.final)
    # [1] TRUE
    

    选项 2 与 a 之前的 b: 只需交换传递给 paste() 的未命名的 Map() 参数。

    ra <- rep(a, length(b))
    Map(paste, relist(rep(b, each=sum(lengths(a))), ra), ra, sep = ".")
    

    【讨论】:

    • 就是这样!非常感谢
    【解决方案2】:

    保持接近 OP 的方法,这可以通过使用匿名函数的嵌套 lapply() 来解决:

    unlist(lapply(b, function(x) lapply(a, function(y) paste(x, y, sep = "."))), 
           recursive = FALSE)
    
    [[1]]
    [1] "A.sp1.var1" "A.sp1.var2"
    
    [[2]]
    [1] "A.sp1.var1" "A.sp1.var3"
    
    [[3]]
    [1] "A.sp1.var1" "A.sp1.var4"
    
    ...
    
    [[34]]
    [1] "B.sp3.var2" "B.sp3.var3"
    
    [[35]]
    [1] "B.sp3.var2" "B.sp3.var4"
    
    [[36]]
    [1] "B.sp3.var3" "B.sp3.var4"
    

    注意,b 粘贴在a 前面。 unlist() 是展平顶级列表所必需的。

    验证方法是否有效(b 前面的a 与a.final 比较):

    identical(a.final,
              unlist(lapply(b, function(x) lapply(a, function(y) paste(y, x, sep = "."))), 
                     recursive = FALSE))
    
    [1] TRUE
    

    【讨论】:

      【解决方案3】:

      这是一种完全不同的方法,它从头开始创建标签并将它们返回到 36 行 x 2 列的 data.table 中,而不是具有 36 个长度为 2 的向量的列表:

      library(data.table)
      # cross join of treat, spec, var. Note, full labels will be created in sprintf() below
      DT <- CJ(LETTERS[1:2], 1:3, 1:4)
      # non equi join as replacement of combn()
      DT[DT, on = .(V1, V2, V3 > V3), nomatch = 0L,
         # create labels
         .(sprintf("%s.sp%s.var%i", V1, V2, V3), 
           sprintf("%s.sp%s.var%i", V1, V2, x.V3))]
      
                  V1         V2
       1: A.sp1.var1 A.sp1.var2
       2: A.sp1.var1 A.sp1.var3
       3: A.sp1.var1 A.sp1.var4
       4: A.sp1.var2 A.sp1.var3
       5: A.sp1.var2 A.sp1.var4
       6: A.sp1.var3 A.sp1.var4
       7: A.sp2.var1 A.sp2.var2
      ...
      29: B.sp2.var2 B.sp2.var4
      30: B.sp2.var3 B.sp2.var4
      31: B.sp3.var1 B.sp3.var2
      32: B.sp3.var1 B.sp3.var3
      33: B.sp3.var1 B.sp3.var4
      34: B.sp3.var2 B.sp3.var3
      35: B.sp3.var2 B.sp3.var4
      36: B.sp3.var3 B.sp3.var4
                  V1         V2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-17
        • 2019-05-19
        • 1970-01-01
        • 2019-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多