按行名称合并多个数据框

问题描述 投票:0回答:4

我正在尝试按行名称合并多个数据框。

我知道如何用两个来做:

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

最好的方法是什么?

r merge dataframe reshape
4个回答
15
投票

通过

row.names
进行合并会产生奇怪的事情 - 它会创建一个名为 Row.names 的列,这使得后续合并变得困难。

为了避免这个问题,您可以创建一个包含行名称的列(无论如何,这通常是一个更好的主意 - 行名称非常有限并且难以操作)。使用OP中给出的数据执行此操作的一种方法(不是最佳方法,为了处理矩形数据的更优化和更简单的方法,我建议改为了解

data.table
):

Reduce(merge, lapply(l, function(x) data.frame(x, rn = row.names(x))))

2
投票

也许存在使用

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
),因为整个
...
参数都用于要合并的对象列表中。


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

0
投票

与当前答案类似的 tidyverse 解决方案是:

library(purrr)
library(dplyr)

reduce(map(l, ~ as_tibble(.x, rownames = "rn")), full_join, by = "rn")
© www.soinside.com 2019 - 2024. All rights reserved.