【问题标题】:Merge data.frame in R在 R 中合并 data.frame
【发布时间】:2018-08-27 08:32:41
【问题描述】:

我有一个关于在 R 中使用 data.frame 进行特定类型合并的问题(发现很多类似的问题,但无法解决我的特定问题)

假设我有两个数据框,每个数据框有两列 X1,X2:

df1 =

            X1         X2
    1  '01.01.2000'    4
    2  '01.01.2001'    5
    3  '01.01.2002'    6

df2 =

            X1         X2
    1  '01.01.2002'    8
    2  '01.01.2003'    9
    3  '01.01.2004'    10

我想要的是根据以下规则合并的数据框:

  1. 如果X1中的值仅在df1中,则使用df1X2的值
  2. 如果X1 中的值同时存在于df1df2 中,则使用X2 中的值df2
  3. 如果X1中的值仅在df2中,则使用df2X2的值

对于上面的df1df2,这意味着:

dfMerged =

            X1         X2
    1  '01.01.2000'    4
    2  '01.01.2001'    5
    3  '01.01.2002'    8
    4  '01.01.2003'    9
    5  '01.01.2004'    10

目前,我通过先合并然后迭代所有行来使用非常慢的解决方案。还尝试了使用 dplyr::Union 等的各种方法,但找不到合适的解决方案。 非常感谢任何帮助!

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    您可以使用以下内容。它只是行绑定data.frames,如果重复(基于X1),df1的行将被删除。

    library(dplyr)
    df1 <- data.frame(X1 = c("01.01.2000", "01.01.2001", "01.01.2002"),
                      X2 = c(4, 5, 6), stringsAsFactors = F)
    df2 <- data.frame(X1 = c("01.01.2002", "01.01.2003", "01.01.2004"),
                      X2 = c(8, 9, 10), stringsAsFactors = F)
    
    dfMerged <- bind_rows(df2, df1) %>% 
      distinct(X1, .keep_all = TRUE) %>% 
      arrange(X1, X2)
    

    【讨论】:

      【解决方案2】:

      数据

      df1 <- structure(list(X1 = c("01.01.2000", "01.01.2001", "01.01.2002"), 
                            X2 = 4:6), 
                       class = "data.frame", 
                       row.names = c(NA, -3L))
      
      df2 <- structure(list(X1 = c("01.01.2002", "01.01.2003", "01.01.2004"), 
                            X2 = 8:10), 
                       class = "data.frame", 
                       row.names = c(NA, -3L))
      

      代码

      library(dplyr)
      full_join(df1, df2, by = "X1") %>%
          mutate(X2 = case_when(!is.na(X2.x) & !is.na(X2.y) ~ X2.y, 
                                is.na(X2.y)                 ~ X2.x, 
                                is.na(X2.x)                 ~ X2.y)) %>% 
          select(X1, X2)
      

      说明

      1. 首先,您对两个数据集执行full_join,并将X1 作为连接列。这将创建列 X2.xX2.y,它们将承载各自数据集的 X2 值。
      2. 那么只需简单地应用mutate 即可根据您给出的规则选择正确的列。

      基准测试

      distinct 解决方案无论如何都比3 快,如以下基准所示:

      library(tidyverse)
      library(microbenchmark)
      make_data_frame <- function(n, percent_matching = .1) {
         ids_a <- ids_b <- paste0("ID_", seq.int(n))
         non_matching_ids <- sample(n, round(n * (1 - percent_matching), 0))
         ids_b[non_matching_ids] <- paste(ids_b[non_matching_ids], "b", sep = "_")
         list(A = data.frame(X1 = ids_a, X2 = "a", stringsAsFactors = FALSE),
              B = data.frame(X1 = ids_b, X2 = "b", stringsAsFactors = FALSE))
      }
      
      .distinct <- function(dfs) {
         bind_rows(dfs$B, dfs$A) %>% 
            distinct(X1, .keep_all = TRUE)
      }
      
      .join <- function(dfs) {
         full_join(dfs$A, dfs$B, by = "X1") %>%
            mutate(X2 = case_when(!is.na(X2.x) & !is.na(X2.y) ~ X2.y, 
                                  is.na(X2.y)                 ~ X2.x, 
                                  is.na(X2.x)                 ~ X2.y))
      }
      scenarios <- expand.grid(n = c(1e4, 1e5, 1e6),
                               percent_matching = c(.1, .5, .9))
      all_data <- pmap(scenarios, make_data_frame)
      all_mb <- map(all_data, ~ microbenchmark(.distinct(.x), .join(.x)))
      map_dfr(seq.int(NROW(scenarios)), function(i) {
         mdat <- scenarios[i, ]
         my_summary <- summary(all_mb[[i]])
         rownames(mdat) <- NULL
         rownames(my_summary) <- NULL
         cbind(mdat, my_summary)
      }) %>%
      select(n, percent_matching, expr, mean)
      

      #        n percent_matching          expr        mean
      # 1  1e+04              0.1 .distinct(.x)    4.975013
      # 2  1e+04              0.1     .join(.x)   12.587072
      # 3  1e+05              0.1 .distinct(.x)   59.577142
      # 4  1e+05              0.1     .join(.x)  149.987451
      # 5  1e+06              0.1 .distinct(.x)    1.158597
      # 6  1e+06              0.1     .join(.x)    2.699003
      # 7  1e+04              0.5 .distinct(.x)    4.485196
      # 8  1e+04              0.5     .join(.x)   11.902656
      # 9  1e+05              0.5 .distinct(.x)   46.660016
      # 10 1e+05              0.5     .join(.x)  132.180758
      # 11 1e+06              0.5 .distinct(.x)  913.503111
      # 12 1e+06              0.5     .join(.x) 2148.531600
      # 13 1e+04              0.9 .distinct(.x)    4.299905
      # 14 1e+04              0.9     .join(.x)   12.731292
      # 15 1e+05              0.9 .distinct(.x)   37.558069
      # 16 1e+05              0.9     .join(.x)  111.428117
      # 17 1e+06              0.9 .distinct(.x)  458.030035
      # 18 1e+06              0.9     .join(.x) 1458.408847
      

      【讨论】:

        猜你喜欢
        • 2013-01-24
        • 1970-01-01
        • 1970-01-01
        • 2013-12-04
        • 2015-07-11
        • 2017-03-14
        • 1970-01-01
        • 2014-08-12
        • 2019-03-28
        相关资源
        最近更新 更多