【问题标题】:lapply a paste0 function over a list在列表上应用 paste0 函数
【发布时间】:2021-09-20 11:34:27
【问题描述】:

具有可重现示例的数据

我有以下列表

library(arrangements)

a <- list(
arrangements::combinations(x = 5, k = 5),
arrangements::combinations(x = 5, k = 4),
arrangements::combinations(x = 4, k = 4))

看起来像这样:

[[1]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5

[[2]]
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    1    2    3    5
[3,]    1    2    4    5
[4,]    1    3    4    5
[5,]    2    3    4    5

[[3]]
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4

我需要什么

我想在列表a(即[[1]], [[2]], [[3]])的每个元素的每一行上使用一些函数,以便输出如下所示:

[[1]]
"F1 =~ 1 + 2 + 3 + 4 +5"

[[2]]
"F2 =~ 1 + 2 + 3 + 4" 
"F3 =~ 1 + 2 + 3 + 5" 
"F4 =~ 1 + 2 + 4 + 5" 
"F5 =~ 1 + 3 + 4 + 5"
"F6 =~ 2 + 3 + 4 + 5"

[[3]]
"F7 =~ 2 + 3 + 4 + 5"

到目前为止我已经做了什么以及我被困在哪里

我已经设法为列表的各个元素生成了我需要的输出。例如,下面的 for 循环会产生我需要的输出,但仅适用于列表 a 的第二个元素。

z <- list(
arrangements::combinations(x = 5, k = 4))

qq <- vector(mode = "character", length = 0L)

    for(i in 1:5) {
            qq[i] <- paste0("F", i+1, sep = " =~ ", paste(z[[1]][i, ], collapse=" + "))
}   

qq

[1] "F2 =~ 1 + 2 + 3 + 4" "F3 =~ 1 + 2 + 3 + 5" "F4 =~ 1 + 2 + 4 + 5" "F5 =~ 1 + 3 + 4 + 5"
[5] "F6 =~ 2 + 3 + 4 + 5"

我无法为整个列表编写 for 循环,因为列表的每个元素都有不同的维度,并且我收到下标超出范围的错误。此外,我无法处理列表 a 的各个元素,因为它是一个示例,并且列表可能要大得多,所以我需要一种方法来自动化它。

我怀疑这可以通过结合lapplyapply 来完成,但我只是不知道如何使它工作。例如,这里 lapplyapply 一起工作,但我就是不知道如何让它们输出我需要的东西。

lapply(a, function(x) apply(a[[2]], 1, paste, collapse=""))

提前谢谢你

【问题讨论】:

    标签: r list apply lapply paste


    【解决方案1】:

    使用reformulate()

    b <- lapply(a, \(i) 
                apply(i, 1, \(x) 
                      Reduce(paste0, as.character(reformulate(as.character(x))))))
    b <- Map(\(x, y) paste(sprintf('F%s=', seq(b[[y]]) + x), b[[y]]),
        c(0, cumsum(lengths(b)[-length(b)])), seq(b))
    

    使用RcppAlgos::comboGeneral() 的替代方法可能比带有FUN= 参数的arrangements::combinations 更有优势。 (注意: 只需将 comboGeneral() 替换为 combn() 即可获得纯基础 R 选项)。

    library(RcppAlgos)
    b <- Map(\(x, m) comboGeneral(as.character(x), m, FUN=\(i) 
                           Reduce(paste0, as.character(reformulate(i)))),
             lapply(c(5, 5, 4), seq), c(5, 4, 4))
    b <- Map(\(x, y) paste(sprintf('F%s=', seq(b[[y]]) + x), b[[y]]),
        c(0, cumsum(lengths(b)[-length(b)])), seq(b))
    

    结果:

    b
    # [[1]]
    # [1] "F1= ~1 + 2 + 3 + 4 + 5"
    # 
    # [[2]]
    # [1] "F2= ~1 + 2 + 3 + 4" "F3= ~1 + 2 + 3 + 5" "F4= ~1 + 2 + 4 + 5"
    # [4] "F5= ~1 + 3 + 4 + 5" "F6= ~2 + 3 + 4 + 5"
    # 
    # [[3]]
    # [1] "F7= ~1 + 2 + 3 + 4"
    

    【讨论】:

      【解决方案2】:

      使用Mapsprintf -

      nr <- sapply(a, nrow)
      Map(function(x, y) sprintf('F%d = ~%s', (y - nrow(x) + 1):y, 
                         apply(x, 1,paste0, collapse = '+')), a, cumsum(nr))
      
      #[[1]]
      #[1] "F1 = ~1+2+3+4+5"
      
      #[[2]]
      #[1] "F2 = ~1+2+3+4" "F3 = ~1+2+3+5" "F4 = ~1+2+4+5" "F5 = ~1+3+4+5"
      #[5] "F6 = ~2+3+4+5"
      
      #[[3]]
      #[1] "F7 = ~1+2+3+4"
      

      nr用于统计a的每个矩阵的行数。在Map 中,我们传递矩阵列表anr 的累积和,这将告诉我们每个序列将在哪里结束(cumsum(nr))。在函数中,我们使用此信息来获取序列的开始 ((y - nrow(x) + 1)),然后逐行粘贴矩阵以获得所需的输出。

      【讨论】:

      • 非常感谢您的帮助。对此,我真的非常感激。您能否简要概述一下代码的作用,以增强我个人对其背后逻辑的学习?提前谢谢你
      • @PsychometStats 我在答案中添加了一些解释。
      【解决方案3】:

      我认为这可以满足您的需求。诀窍是生成由单行组成的第二个列表a2,以便 F 的编号正常工作...

      a2 <- unlist(lapply(a, apply, 1, identity, simplify = FALSE), #separates the rows
                   recursive = FALSE)                               #keeps as list
      
      relist(sapply(seq_along(a2),                                  #to get overall id no i
                    function(i) paste0("F", i, " =~ ", 
                                       paste(a2[i][[1]], collapse=" + "))),
             lapply(a, rowSums))                                    #a list for relisting by
      
      [[1]]
      [1] "F1 =~ 1 + 2 + 3 + 4 + 5"
      
      [[2]]
      [1] "F2 =~ 1 + 2 + 3 + 4" "F3 =~ 1 + 2 + 3 + 5" "F4 =~ 1 + 2 + 4 + 5" 
          "F5 =~ 1 + 3 + 4 + 5" "F6 =~ 2 + 3 + 4 + 5"
      
      [[3]]
      [1] "F7 =~ 1 + 2 + 3 + 4"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-08
        • 2021-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-06
        相关资源
        最近更新 更多