我有一个要合并的许多 data.frames 的列表。这里的问题是每个 data.frame 在行数和列数方面都不同,但它们都共享关键变量(我在下面的代码中已经调用"var1"过"var2")。如果 data.frames 在列方面是相同的,我只能rbind,plyr 的rbind.fill可以完成这项工作,但这些数据并非如此。
"var1"
"var2"
rbind
因为该merge命令仅适用于 2 个 data.frames,所以我转向互联网寻求想法。我从这里得到了这个,它在 R 2.7.2 中完美运行,这就是我当时所拥有的:
merge
merge.rec <- function(.list, ...){ if(length(.list)==1) return(.list[[1]]) Recall(c(list(merge(.list[[1]], .list[[2]], ...)), .list[-(1:2)]), ...) }
我会这样调用函数:
df <- merge.rec(my.list, by.x = c("var1", "var2"), by.y = c("var1", "var2"), all = T, suffixes=c("", ""))
但是在 2.7.2 之后的任何 R 版本中,包括 2.11 和 2.12,此代码都会失败并出现以下错误:
Error in match.names(clabs, names(xi)) : names do not match previous names
有没有办法解决这个问题?
另一个问题专门询问了如何在 R 中使用 dplyr执行多个左连接。这个问题被标记为这个问题的副本,所以我在这里回答,使用下面的 3 个示例数据框:
x <- data.frame(i = c("a","b","c"), j = 1:3, stringsAsFactors=FALSE) y <- data.frame(i = c("b","c","d"), k = 4:6, stringsAsFactors=FALSE) z <- data.frame(i = c("c","d","a"), l = 7:9, stringsAsFactors=FALSE)
2018 年 6 月更新 :我将答案分为三个部分,代表执行合并的三种不同方式。purrr如果您已经在使用 tidyverse 软件包,您可能想要使用这种方式。出于以下比较目的,您将找到使用相同示例数据集的基本 R 版本。
purrr
reduce 1)从包中加入他们purrr:
reduce
该purrr包提供了reduce一个语法简洁的函数:
library(tidyverse) list(x, y, z) %>% reduce(left_join, by = "i") # A tibble: 3 x 4 # i j k l # <chr> <int> <int> <int> # 1 a 1 NA 9 # 2 b 2 4 NA # 3 c 3 5 7
您还可以执行其他联接,例如 afull_join或inner_join:
full_join
inner_join
list(x, y, z) %>% reduce(full_join, by = "i") # A tibble: 4 x 4 # i j k l # <chr> <int> <int> <int> # 1 a 1 NA 9 # 2 b 2 4 NA # 3 c 3 5 7 # 4 d NA 6 8 list(x, y, z) %>% reduce(inner_join, by = "i") # A tibble: 1 x 4 # i j k l # <chr> <int> <int> <int> # 1 c 3 5 7
2)dplyr::left_join()以 R 为基数Reduce():
dplyr::left_join()
Reduce()
list(x,y,z) %>% Reduce(function(dtf1,dtf2) left_join(dtf1,dtf2,by="i"), .) # i j k l # 1 a 1 NA 9 # 2 b 2 4 NA # 3 c 3 5 7
3) 基数 Rmerge()与基数 R Reduce():
merge()
出于比较目的,这里是基于查尔斯回答的左连接的基本 R 版本。
Reduce(function(dtf1, dtf2) merge(dtf1, dtf2, by = "i", all.x = TRUE), list(x,y,z)) # i j k l # 1 a 1 NA 9 # 2 b 2 4 NA # 3 c 3 5 7