【问题标题】:cbind with partially nested listcbind 与部分嵌套列表
【发布时间】:2017-12-22 09:58:26
【问题描述】:

我正在尝试 cbindunnestas.data.table 部分嵌套列表。

id <- c(1,2)
A <- c("A1","A2","A3")
B <- c("B1")
AB <- list(A=A,B=B)
ABAB <- list(AB,AB)
nested_list <- list(id=id,ABAB=ABAB)

id 的length 与ABAB 相同(本例中为2)。我不知道如何unlist 此列表的一部分 (ABAB) 和 cbind 另一部分 (id)。这是我想要的结果,data.table

data.table(id=c(1,1,1,2,2,2),A=c("A1","A2","A3","A1","A2","A3"),B=rep("B1",6))
   id  A  B
1:  1 A1 B1
2:  1 A2 B1
3:  1 A3 B1
4:  2 A1 B1
5:  2 A2 B1
6:  2 A3 B1

【问题讨论】:

  • 我假设您想要一个以一般方式解决这种情况的解决方案...
  • @ChiPak 我使用 ABAB 包含相同列表两次(AB,AB)的示例数据使其变得简单。我的真实示例,包含不同的列表 (ABAB &lt;- list(AB,CD))

标签: r list data.table nested-lists


【解决方案1】:

我没有测试更一般的情况,但这适用于 OP 示例:

library(data.table)

as.data.table(nested_list)[, lapply(ABAB, as.data.table)[[1]], id]
#   id  A  B
#1:  1 A1 B1
#2:  1 A2 B1
#3:  1 A3 B1
#4:  2 A1 B1
#5:  2 A2 B1
#6:  2 A3 B1

或者另一种选择(可能更快,但更冗长):

rbindlist(lapply(nested_list$ABAB, as.data.table),
          idcol = 'id')[, id := nested_list$id[id]]

【讨论】:

    【解决方案2】:

    这是一些超级丑陋的基础 R,但会产生所需的输出。

    Reduce(rbind, Map(function(x, y) setNames(data.frame(x, y), c("id", "A", "B")),
                      as.list(nested_list[[1]]),
                      lapply(unlist(nested_list[-1], recursive=FALSE),
                             function(x) Reduce(cbind, x))))
      id  A  B
    1  1 A1 B1
    2  1 A2 B1
    3  1 A3 B1
    4  2 A1 B1
    5  2 A2 B1
    6  2 A3 B1
    

    lapply 获取使用unlistrecursive=FALSE 提取的两个元素(每个包含A 和B 变量)的列表。它返回一个字符矩阵列表,其中 B 变量由回收填充。来自as.list(nested_list[[1]]) 的单个 id 变量的列表和矩阵的光照被馈送到Map,它将相应的对转换为 data.frame 并为列提供所需的名称并返回 data.frames 的列表。最后,这个 data.frames 列表被提供给 Reducerbinds 将结果发送到单个 data.frame。

    如果需要,最后的 Reduce(rbind, 可以替换为 data.tables rbindlist

    【讨论】:

      【解决方案3】:

      这是另一个可怕的解决方案

      max_length = max(unlist(lapply(nested_list, function(x) lapply(x, lengths))))
      data.frame(id = do.call(c, lapply(nested_list$id, rep, max_length)), 
                 do.call(rbind, lapply(nested_list$ABAB, function(x)
                     do.call(cbind, lapply(x, function(y) {
                         if(length(y) < max_length) {
                             rep(y, max_length)
                         } else {
                             y
                         }
                     })))))
      #  id  A  B
      #1  1 A1 B1
      #2  1 A2 B1
      #3  1 A3 B1
      #4  2 A1 B1
      #5  2 A2 B1
      #6  2 A3 B1
      

      【讨论】:

        【解决方案4】:

        还有一个,也很不雅 - 但当我看到其他答案时,我已经走得太远了。

        restructure <- function(nested_l) {
          ids <- as.numeric(max(unlist(lapply(unlist(nested_l, recursive = FALSE), function(x){
            lapply(x, length)
          }))))
        
          temp = data.frame(rep(nested_l$id, each = ids), 
                     sapply(1:length(nested_l$id), function(x){
                       out <-unlist(lapply(nested_l[[2]], function(y){
                         return(y[x])
                       }))
                     }))
          names(temp) <- c("id", unique(substring(unlist(nested_l[2]), first = 1, last = 1)))
          return(temp)
        }
        
        > restructure(nested_list)
          id  A  B
        1  1 A1 B1
        2  1 A2 B1
        3  1 A3 B1
        4  2 A1 B1
        5  2 A2 B1
        6  2 A3 B1
        

        【讨论】:

          【解决方案5】:

          入党:

          library(tidyverse)
          temp <- map(nested_list,~map(.x,~expand.grid(.x)))
          df <- map_df(1:2,~cbind(temp$id[[.x]],temp$ABAB[[.x]]))
          
            Var1  A  B
          1    1 A1 B1
          2    1 A2 B1
          3    1 A3 B1
          4    2 A1 B1
          5    2 A2 B1
          6    2 A3 B1
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-05-28
            • 2021-12-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多