繁体   English   中英

合并R中的data.frame

[英]Merge data.frame in R

我有一个关于使用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 ,使用的值X2df1
  2. 如果X1的值同时在df1df2使用df2X2 df2
  3. 如果X1的值仅在df2 ,则在df2中使用X2df2

对于上面的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等的各种方法,但找不到合适的解决方案。 任何帮助是极大的赞赏!

您可以使用以下内容。 它只是行绑定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)

数据

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. 首先,在X1和连接列的两个数据集上执行full_join 这将创建列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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM