按行名合并 R 中超过 2 个数据框

Posted

技术标签:

【中文标题】按行名合并 R 中超过 2 个数据框【英文标题】:Merging more than 2 dataframes in R by rownames 【发布时间】:2013-05-16 00:31:27 【问题描述】:

我从 4 个 df 收集数据,并希望按行名合并它们。我正在寻找一种有效的方法来做到这一点。这是我拥有的数据的简化版本。

df1           <- data.frame(N= sample(seq(9, 27, 0.5), 40, replace= T),
                            P= sample(seq(0.3, 4, 0.1), 40, replace= T),
                            C= sample(seq(400, 500, 1), 40, replace= T))
df2           <- data.frame(origin= sample(c("A", "B", "C", "D", "E"), 40,
                                           replace= T),
                            foo1= sample(c(T, F), 40, replace= T),
                            X= sample(seq(145600, 148300, 100), 40, replace= T),
                            Y= sample(seq(349800, 398600, 100), 40, replace= T))
df3           <- matrix(sample(seq(0, 1, 0.01), 40), 40, 100)
df4           <- matrix(sample(seq(0, 1, 0.01), 40), 40, 100)
rownames(df1) <- paste("P", sprintf("%02d", c(1:40)), sep= "")
rownames(df2) <- rownames(df1)
rownames(df3) <- rownames(df1)
rownames(df4) <- rownames(df1)

这是我通常会做的:

# merge df1 and df2
dat           <- merge(df1, df2, by= "row.names", all.x= F, all.y= F) #merge
rownames(dat) <- dat$Row.names #reset rownames
dat$Row.names <- NULL  #remove added rownames col

# merge dat and df3
dat           <- merge(dat, df3, by= "row.names", all.x= F, all.y= F) #merge
rownames(dat) <- dat$Row.names #reset rownames
dat$Row.names <- NULL  #remove added rownames col

# merge dat and df4
dat           <- merge(dat, df4, by= "row.names", all.x= F, all.y= F) #merge
rownames(dat) <- dat$Row.names #reset rownames
dat$Row.names <- NULL #remove added rownames col

如您所见,这需要大量代码。我的问题是,是否可以通过更简单的方法实现相同的结果。我试过了(没有成功):更新:现在可以了!

MyMerge       <- function(x, y)
  df            <- merge(x, y, by= "row.names", all.x= F, all.y= F)
  rownames(df)  <- df$Row.names
  df$Row.names  <- NULL
  return(df)

dat           <- Reduce(MyMerge, list(df1, df2, df3, df4))

提前感谢您的任何建议

【问题讨论】:

without success 到底是什么意思?请更具体,包括错误。更好的是,创建一个可重现的示例。 1.) 如果行名对您的数据结构非常重要,以至于您需要通过这些行名进行合并,为什么不直接将 data.frame 用作一个真正的列呢?这为您节省了大部分编码。 2.) 即使保留它们,也可以节省大量编码,请参阅merge 参数by.xby.y 3.) 可以使用df$Row.Names &lt;- NULL 4.) 从 data.frame 中删除列Reduce 方法应该确实有效,我也想知道为什么会失败。 我已经包含了一些示例数据。我还发现 的建议方法毕竟确实有效。问题是我想合并 df 中的单个列,从而删除行名信息。 但是,在此设置中,仅保留相交的行名 all.x= Fall.y= F。是否可以保留 df1 的所有行,但从其他 df 中排除不是%in% rownames(df1) 的行,即all.x= T, all.y= F 好的,Ove 也解决了最后一个问题。只需在“MyMerge”功能中调整all.x= T, all.y= T。感谢您观看@Paul 和@Basterfield。 【参考方案1】:

三行代码会给你完全相同的结果:

dat2 <- cbind(df1, df2, df3, df4)
colnames(dat2)[-(1:7)] <- paste(paste('V', rep(1:100, 2),sep = ''),
                            rep(c('x', 'y'), each = 100), sep = c('.'))
all.equal(dat,dat2)    

啊,我明白了,现在我明白你为什么会这么痛苦了。使用旧的for 循环肯定可以解决问题。也许还有更聪明的解决方案

rn <- rownames(df1)
l <- list(df1, df2, df3, df4)
dat <- l[[1]]
for(i in 2:length(l)) 
  dat <- merge(dat, l[[i]],  by= "row.names", all.x= F, all.y= F) [,-1]
  rownames(dat) <- rn

【讨论】:

您好,感谢您的回复。我看看结果如何。但是,我承认我在示例数据中没有说清楚,我希望这在 rownames 不同时也能正常工作。因此,在示例中,行名是相等的,但是当行被打乱时,处理应该仍然有效,或者如果例如df2 有更多或更少的行。这就是我选择merge的原因。【参考方案2】:

来自plyrjoin_all 可能会做你想做的事。但它们都必须是数据框,并且行名作为列添加

require(plyr)

df3 <- data.frame(df3)
df4 <- data.frame(df4)

df1$rn <- rownames(df1)
df2$rn <- rownames(df2)
df3$rn <- rownames(df3)
df4$rn <- rownames(df4)

df <- join_all(list(df1,df2,df3,df4), by = 'rn', type = 'full')

type 参数应该有帮助,即使行名不同且不匹配 如果您不想要这些行名:

df$rn <- NULL

【讨论】:

【参考方案3】:

编辑你的函数,我想出了一个函数,它允许你通过特定的列键(列的名称)合并更多的数据框。结果数据框包括合并数据框的所有变量(如果您只想保留公共变量(不包括 NA,请使用:all.x= FALSE, all.y= FALSE

MyMerge <- function(x, y)
  df <- merge(x, y, by= "name of the common column", all.x= TRUE, all.y= TRUE)
  return(df)

new.df <- Reduce(MyMerge, list(df1, df2, df3, df4))

【讨论】:

不错的函数,有没有这个函数可以重命名列名,并将不同的列名赋予常见的列名? 合并两个数据框后,我通常使用“fix()”函数来编辑数据库——因此你也可以重命名列。【参考方案4】:

我一直在寻找相同的功能。在尝试了这里的几个选项和其他地方的其他选项之后。对我来说最简单的是:

cbind.data.frame( df1,df2,df3,df4....)

【讨论】:

这仅适用于您的行在每个数据框中的顺序相同的情况。

以上是关于按行名合并 R 中超过 2 个数据框的主要内容,如果未能解决你的问题,请参考以下文章

基于R中的行名合并数据框

按行名合并或组合

按行分组时如何合并熊猫数据框的字典

python--pandas合并与连接

如何在处理 r 中超过 500 万个观测值的数据框时加快迭代速度?

来自两个数据帧的总数据按行名匹配