【问题标题】:R: merge two lists of lists of dataframesR:合并两个数据框列表列表
【发布时间】:2018-05-20 05:28:57
【问题描述】:

我有两个这样的数据框列表:

L1 <- list(Q1=list(A=data.frame(X1=1:3),C=data.frame(X1=1:3)),
        Q2=list(B=data.frame(X1=1:3),C=data.frame(X1=1:3)))
L2 <- list(Q1=list(B=data.frame(X1=4:6),C=data.frame(X1=4:6)),
        Q2=list(A=data.frame(X1=4:6),C=data.frame(X1=4:6)))

第一级“Q1”和“Q2”的名称在两个列表中是相同的。

我想合并两个列表,以便将具有相同名称(例如“$Q1$C”)的数据框与rbind 组合在一起,并将新的数据框添加到列表中。所需的输出应如下所示:

> L3
$Q1
$Q1$A
  X1
1  1
2  2
3  3

$Q1$B
  X1
1  4
2  5
3  6

$Q1$C
  X1
1  1
2  2
3  3
4  4
5  5
6  6


$Q2
$Q2$A
  X1
1  4
2  5
3  6

$Q2$B
  X1
1  1
2  2
3  3

$Q2$C
  X1
1  1
2  2
3  3
4  4
5  5
6  6

我尝试了一些使用Map()lapply() 的组合,但我无法修复它。例如:

L3 <- Map('rbind',lapply(L1,'['),lapply(L2,'['))

感谢任何帮助!

【问题讨论】:

    标签: r list merge lapply mapply


    【解决方案1】:

    这是使用基础 R 的解决方案:

    x <- c(L1, L2)
    lapply(split(x, names(x)), function(i){
        xsub <- do.call(c, unname(i))
        lapply(split(xsub, names(xsub)), function(j) do.call(rbind, unname(j)))
    })
    
    • split(x, names(x)) 将把Q1s 和Q2s 放在一起;
    • xsub &lt;- do.call(c, unname(i)) 会将Q1s 或Q2s 组合成一个列表data.frames
    • split(xsub, names(xsub)) 将按名称对data.frames 进行分组(ABC);

    输出是:

    # $Q1
    # $Q1$A
    # X1
    # 1  1
    # 2  2
    # 3  3
    # 
    # $Q1$B
    # X1
    # 1  4
    # 2  5
    # 3  6
    # 
    # $Q1$C
    # X1
    # 1  1
    # 2  2
    # 3  3
    # 4  4
    # 5  5
    # 6  6
    # 
    # 
    # $Q2
    # $Q2$A
    # X1
    # 1  4
    # 2  5
    # 3  6
    # 
    # $Q2$B
    # X1
    # 1  1
    # 2  2
    # 3  3
    # 
    # $Q2$C
    # X1
    # 1  1
    # 2  2
    # 3  3
    # 4  4
    # 5  5
    # 6  6
    

    【讨论】:

    • 我也喜欢这个没有库的解决方案。谢谢!我想知道是否有我正在尝试的单线解决方案,但您的似乎是一种优雅的方式。太好了!
    【解决方案2】:

    这是一种使用reshape2::melt的方法。

    library(reshape2);
    
    # Collapse lists and turn into long dataframe
    df.long <- rbind.data.frame(
        melt(L1, id.vars = "X1"),
        melt(L2, id.vars = "X1"));
    
    # Split dataframe into nested list
    lst <- lapply(split(df.long, df.long$L1), function(x) split(x, x$L2));
    lst <- lapply(lst, function(x) lapply(x, function(y) data.frame(X1 = y$X1)));
    
    str(lst);
    #List of 2
    # $ Q1:List of 3
    #  ..$ A:'data.frame':  3 obs. of  1 variable:
    #  .. ..$ X1: int [1:3] 1 2 3
    #  ..$ B:'data.frame':  3 obs. of  1 variable:
    #  .. ..$ X1: int [1:3] 4 5 6
    #  ..$ C:'data.frame':  6 obs. of  1 variable:
    #  .. ..$ X1: int [1:6] 1 2 3 4 5 6
    # $ Q2:List of 3
    #  ..$ A:'data.frame':  3 obs. of  1 variable:
    #  .. ..$ X1: int [1:3] 4 5 6
    #  ..$ B:'data.frame':  3 obs. of  1 variable:
    #  .. ..$ X1: int [1:3] 1 2 3
    #  ..$ C:'data.frame':  6 obs. of  1 variable:
    #  .. ..$ X1: int [1:6] 1 2 3 4 5 6
    

    数据

    L1 <- list(Q1=list(A=data.frame(X1=1:3),C=data.frame(X1=1:3)),
            Q2=list(B=data.frame(X1=1:3),C=data.frame(X1=1:3)))
    L2 <- list(Q1=list(B=data.frame(X1=4:6),C=data.frame(X1=4:6)),
            Q2=list(A=data.frame(X1=4:6),C=data.frame(X1=4:6)))
    

    【讨论】:

      【解决方案3】:

      使用咕噜声:

      library(tidyverse)
      
      f <- function(x) {
        map_df(map(x, bind_rows, .id = "id1"), bind_rows, .id = "id2")
      }
      
      list(L1, L2) %>%
        map_df(f) %>%
        split(list(.$id1, .$id2)) %>%
        map(select, X1)
      

      【讨论】:

        猜你喜欢
        • 2015-11-06
        • 2020-01-01
        • 1970-01-01
        • 2019-09-19
        • 2016-06-25
        • 1970-01-01
        • 2020-10-16
        • 2019-10-27
        相关资源
        最近更新 更多