我正在尝试按行名合并多个数据框。
我知道怎么做两个:
x = data.frame(a = c(1,2,3), row.names = letters[1:3])
y = data.frame(b = c(1,2,3), row.names = letters[1:3])
merge(x,y, by = "row.names")
但是当我尝试使用reshape
包merge_all()
时,我收到了错误。
z = data.frame(c = c(1,2,3), row.names = letters[1:3])
l = list(x,y,z)
merge_all(l, by = "row.names")
Error in -ncol(df) : invalid argument to unary operator
最好的方法是什么?
答案 0 :(得分:8)
按row.names
进行合并会产生奇怪的结果 - 它会创建一个名为Row.names的列,这会使后续的合并变得困难。
为了避免这个问题,您可以改为创建一个包含行名称的列(无论如何通常都是一个更好的主意 - 行名称非常有限并且难以操作)。使用OP中给出的数据执行此操作的一种方法(不是最佳方式,对于处理矩形数据的更优化和更简单的方法,我建议了解data.table
):
Reduce(merge, lapply(l, function(x) data.frame(x, rn = row.names(x))))
答案 1 :(得分:1)
可能存在使用do.call
或* apply
的更快版本,但这适用于您的情况:
x = data.frame(X = c(1,2,3), row.names = letters[1:3])
y = data.frame(Y = c(1,2,3), row.names = letters[1:3])
z = data.frame(Z = c(1,2,3), row.names = letters[1:3])
merge.all <- function(x, ..., by = "row.names") {
L <- list(...)
for (i in seq_along(L)) {
x <- merge(x, L[[i]], by = by)
rownames(x) <- x$Row.names
x$Row.names <- NULL
}
return(x)
}
merge.all(x,y,z)
重要的是可以定义要转发到by
的函数merge.all
中的所有参数(例如merge
),因为整个...
参数用于要合并的对象列表。
答案 2 :(得分:0)
替代Reduce
和merge
:
如果您将所有数据框放入列表中,则可以使用grep
和cbind
来获取具有所需行名称的数据框。
## set up the data
> x <- data.frame(x1 = c(2,4,6), row.names = letters[1:3])
> y <- data.frame(x2 = c(3,6,9), row.names = letters[1:3])
> z <- data.frame(x3 = c(1,2,3), row.names = letters[1:3])
> a <- data.frame(x4 = c(4,6,8), row.names = letters[4:6])
> lst <- list(a, x, y, z)
## combine all the data frames with row names = letters[1:3]
> gg <- grep(paste(letters[1:3], collapse = ""),
sapply(lapply(lst, rownames), paste, collapse = ""))
> do.call(cbind, lst[gg])
## x1 x2 x3
## a 2 3 1
## b 4 6 2
## c 6 9 3