[英]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
我想要的是根据以下规则合并的数据框:
X1
是仅在df1
,使用的值X2
在df1
X1
的值同时在df1
和df2
使用df2
的X2
df2
X1
的值仅在df2
,则在df2
中使用X2
的df2
对于上面的df1
和df2
,这意味着:
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)
说明
X1
和连接列的两个数据集上执行full_join
。 这将创建列X2.x
和X2.y
,它们将承载相应数据集的X2值。 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.