【问题标题】:Merge data frames in a list by condition in purrr按 purrr 中的条件合并列表中的数据帧
【发布时间】:2021-11-13 05:55:36
【问题描述】:

我有一个具有以下结构的数据框列表:

list_example <- list(type1_a_b = data.frame(id = 1:3, a = 1:3, b = 4:6),
                     type1_c_d = data.frame(id = 1:5, c = 1:5, d = 5:9),
                     type2_e_f = data.frame(id = c(1,3,4), e = 1:3, f = 4:6),
                     type2_g_h = data.frame(id = c(2,3,4), g = 1:3, h = 5:7))

我还有一个数据框类型的向量:

data_types <- c("type1", "type2")

我想按类型(使用 data_types 向量和 id 列)对数据帧进行完全连接,最好使用purrr

期望的输出:

list(type1 = data.frame(id = 1:5,
                        a = c(1:3, NA, NA),
                        b = c(4:6, NA, NA),
                        c = 1:5,
                        d = 5:9),
     
     type2 = data.frame(id = c(1:4),
                        e = c(1, NA, 3, 4),
                        f = c(4, NA, 5, 6),
                        g = c(NA, 1:3),
                        h = c(NA, 5:7))
     )

$type1
  id  a  b c d
1  1  1  4 1 5
2  2  2  5 2 6
3  3  3  6 3 7
4  4 NA NA 4 8
5  5 NA NA 5 9

$type2
  id  e  f  g  h
1  1  1  4 NA NA
2  2 NA NA  1  5
3  3  3  5  2  6
4  4  4  6  3  7

我能够使用this post 的解决方案将所有列表元素减少到一个数据框中,但我希望以列表格式输出,以便以后分别处理不同的数据类型。

list_example %>%
  purrr::reduce(full_join, by = "id")

  id  a  b c d  e  f  g  h
1  1  1  4 1 5  1  4 NA NA
2  2  2  5 2 6 NA NA  1  5
3  3  3  6 3 7  2  5  2  6
4  4 NA NA 4 8  3  6  3  7
5  5 NA NA 5 9 NA NA NA NA

谢谢!

【问题讨论】:

    标签: r list merge purrr


    【解决方案1】:

    我们可以通过名称的子字符串split 并使用mapreduce 循环外部list 内部嵌套的listfull_join

    library(dplyr)
    library(stringr)
    library(purrr)
    list_example %>% 
       split(str_remove(names(.), "_.*")) %>% 
       map(~ reduce(.x, full_join, by = "id") %>%
           arrange(id))
    

    -输出

    $type1
      id  a  b c d
    1  1  1  4 1 5
    2  2  2  5 2 6
    3  3  3  6 3 7
    4  4 NA NA 4 8
    5  5 NA NA 5 9
    
    $type2
      id  e  f  g  h
    1  1  1  4 NA NA
    2  2 NA NA  1  5
    3  3  2  5  2  6
    4  4  3  6  3  7
    

    或在base R 中使用merge/Reduce

    lapply(split(list_example, sub("_.*", "", names(list_example))), 
           \(x) Reduce(\(...) merge(..., all = TRUE), x))
    

    -输出

    $type1
      id  a  b c d
    1  1  1  4 1 5
    2  2  2  5 2 6
    3  3  3  6 3 7
    4  4 NA NA 4 8
    5  5 NA NA 5 9
    
    $type2
      id  e  f  g  h
    1  1  1  4 NA NA
    2  2 NA NA  1  5
    3  3  2  5  2  6
    4  4  3  6  3  7
    

    【讨论】:

    • 谢谢@akrun!按预期工作。花了几个小时来处理我的实际数据(1.4 GB,843 个列表元素,14 种数据类型)。
    【解决方案2】:

    使用lapply 的基本 R 选项 -

    nm <- names(list_example)
    
    result <- lapply(data_types, function(x) 
                Reduce(function(p, q) merge(p, q, all = TRUE, by = 'id'), 
                list_example[grep(x, nm)]))
    result
    
    #[[1]]
    #  id  a  b c d
    #1  1  1  4 1 5
    #2  2  2  5 2 6
    #3  3  3  6 3 7
    #4  4 NA NA 4 8
    #5  5 NA NA 5 9
    
    #[[2]]
    #  id  e  f  g  h
    #1  1  1  4 NA NA
    #2  2 NA NA  1  5
    #3  3  2  5  2  6
    #4  4  3  6  3  7
    

    如果你想命名result列表,你可以添加。

    names(result) <- data_types
    

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 2015-04-26
      • 2013-11-16
      • 2021-08-01
      • 2017-08-30
      相关资源
      最近更新 更多