我有一个列表,里面有很多我想合并的数据帧。这里的问题是,每个data.frame的行数和列数不同,但它们都共享关键变量(在下文中我将其称为“var1”和“var2”)。如果data.frames在列方面是相同的,我可以只rbind,对于plyr的rbind。填充可以完成这项工作,但这些数据不是这样的。
因为merge命令只适用于2 data.frames,所以我求助于互联网。我从这里得到了这个,它在R 2.7.2中完美地工作,这是我当时拥有的:
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
(顺便说一句,我在其他地方看到了这个错误的其他引用,但没有解决方案)。
有办法解决这个问题吗?
我们可以使用{powerjoin}。
从已接受的答案中借用样本数据:
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)
library(powerjoin)
power_full_join(list(x,y,z), by = "i")
#> i j k l
#> 1 a 1 NA 9
#> 2 b 2 4 NA
#> 3 c 3 5 7
#> 4 d NA 6 8
power_left_join(list(x,y,z), by = "i")
#> i j k l
#> 1 a 1 NA 9
#> 2 b 2 4 NA
#> 3 c 3 5 7
您也可以从一个数据帧开始,并加入一个数据帧列表,以获得相同的结果
power_full_join(x, list(y,z), by = "i")
#> i j k l
#> 1 a 1 NA 9
#> 2 b 2 4 NA
#> 3 c 3 5 7
#> 4 d NA 6 8
我将重复使用来自@PaulRougieux的数据示例
x <- data_frame(i = c("a","b","c"), j = 1:3)
y <- data_frame(i = c("b","c","d"), k = 4:6)
z <- data_frame(i = c("c","d","a"), l = 7:9)
这里有一个简短而甜蜜的解决方案,使用purrr和tidyr
library(tidyverse)
list(x, y, z) %>%
map_df(gather, key=key, value=value, -i) %>%
spread(key, value)
我们可以使用{powerjoin}。
从已接受的答案中借用样本数据:
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)
library(powerjoin)
power_full_join(list(x,y,z), by = "i")
#> i j k l
#> 1 a 1 NA 9
#> 2 b 2 4 NA
#> 3 c 3 5 7
#> 4 d NA 6 8
power_left_join(list(x,y,z), by = "i")
#> i j k l
#> 1 a 1 NA 9
#> 2 b 2 4 NA
#> 3 c 3 5 7
您也可以从一个数据帧开始,并加入一个数据帧列表,以获得相同的结果
power_full_join(x, list(y,z), by = "i")
#> i j k l
#> 1 a 1 NA 9
#> 2 b 2 4 NA
#> 3 c 3 5 7
#> 4 d NA 6 8