【问题标题】:R merge two dat frames based on column and listR基于列和列表合并两个数据帧
【发布时间】:2019-02-17 14:02:31
【问题描述】:

无论如何我可以根据列表形式的列合并 R 中的两个数据框以获得其他列的总和。下面的一些示例数据:

df1 <- structure(list(id = c("1", "2"), 
                      band = list(c("c1", "c2", "c3"), "c4"), 
                      samples = list(c(32, 2, 61), 20), 
                      time = list(c(307, 2, 238), 74)), 
                 .Names = c("id", "band", "samples", "time"), 
                 row.names = 0:1, class = "data.frame")

df2 <- structure(list(id = c("1", "3"), 
                      band = list(c("c1", "c4"), "c1"), 
                      samples = list(c(1, 2), 2), 
                      time = list(c(4, 2), 7)), 
                 .Names = c("id", "band", "samples", "time"), 
                 row.names = 0:1, class = "data.frame")

我想根据 id 和 band 列从 df1 和 df2 获取合并数据。不幸的是,bands 列是列表形式,我需要根据bands 列中的元素对样本和时间列求和,该列在列表中。我期待下面的

【问题讨论】:

    标签: r merge


    【解决方案1】:

    一种解决方案是使用 tidyr 包中的 unnestbind_rows 与来自 dplyrgroup_bysummarize 结合使用。

    library(tidyr)
    library(dplyr)
    

    unnest 负责列表列:

    df1_unnest <- df1 %>% 
      unnest()
    
    df1_unnest
    #   id band samples time
    # 1  1   c1      32  307
    # 2  1   c2       2    2
    # 3  1   c3      61  238
    # 4  2   c4      20   74
    
    df2_unnest <- df2 %>% 
      unnest()
    

    bind_rows 结合了两个新的data.frames:

    new_df <- bind_rows(df1_unnest, df2_unnest)
    
    new_df
    #   id band samples time
    # 1  1   c1      32  307
    # 2  1   c2       2    2
    # 3  1   c3      61  238
    # 4  2   c4      20   74
    # 5  1   c1       1    4
    # 6  1   c4       2    2
    # 7  3   c1       2    7
    

    然后使用group_bysummarize_all,您可以将 id 1、波段 c1 的值相加:

    new_df <- new_df %>% 
      group_by(id, band) %>% 
      summarize_all(sum)
    
    new_df
    # A tibble: 6 x 4
    # Groups:   id [?]
    #   id    band  samples  time
    #   <chr> <chr>   <dbl> <dbl>
    # 1 1     c1         33   311
    # 2 1     c2          2     2
    # 3 1     c3         61   238
    # 4 1     c4          2     2
    # 5 2     c4         20    74
    # 6 3     c1          2     7
    

    如果您需要列表列,您可以这样做

    new_df_list <- new_df %>%
      group_by(id) %>% 
      summarize_all(list)
    
    print.data.frame(new_df_list)
    #   id           band      samples           time
    # 1  1 c1, c2, c3, c4 33, 2, 61, 2 311, 2, 238, 2
    # 2  2             c4           20             74
    # 3  3             c1            2              7
    

    【讨论】:

    • @Kath.感谢您的解决方案。只是想知道这对于像 2 或 5 百万行这样的大型数据集来说是否是快速的工作
    • unnest 对于大型数据集需要一些时间,但 bind_rows 应该和 group_bysummarize_all 一样快。我会在您的数据子集上进行尝试。也许您可以进行智能子集化,这样您就不必取消嵌套完整的 data.frame。下次您应该在问题中指定您正在寻找大型数据集的解决方案。
    • 还有一件事,R中的行数有限制吗?
    • 我不知道 - 也许你应该问一个新问题并更具体一些。我认为没有行数限制,而是工作空间容量。
    • 是的.. 我想是的
    猜你喜欢
    • 2020-10-10
    • 2020-07-17
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 2018-05-20
    相关资源
    最近更新 更多