如何合并具有相同列名的多个数据框?
Posted
技术标签:
【中文标题】如何合并具有相同列名的多个数据框?【英文标题】:How can I merge multiple dataframes with the same column names? 【发布时间】:2012-11-26 12:39:30 【问题描述】:我有什么:
我有一个包含以下列的“主”数据框:
userid, condition
由于有四个实验条件,我也有四个携带答案信息的数据框,以下列:
userid, condition, answer1, answer2
现在,我想加入这些,因此所有用户 ID、条件及其对这些条件的答案的组合都会合并。每个条件只应在每行的相应列中有正确答案。
简短、独立的示例:
master = data.frame(userid=c("foo","foo","foo","foo","bar","bar","bar","bar"), condition=c("A","B","C","D","A","B","C","D"))
cond_a = data.frame(userid=c("foo","bar"), condition="A", answer1=c("1","1"), answer2=c("2","2"))
cond_b = data.frame(userid=c("foo","bar"), condition="B", answer1=c("3","3"), answer2=c("4","4"))
cond_c = data.frame(userid=c("foo","bar"), condition="C", answer1=c("5","5"), answer2=c("6","6"))
cond_d = data.frame(userid=c("foo","bar"), condition="D", answer1=c("7","7"), answer2=c("8","8"))
如何将所有条件合并到主表中,使主表如下所示?
userid condition answer1 answer2
1 bar A 1 2
2 bar B 3 4
3 bar C 5 6
4 bar D 7 8
5 foo A 1 2
6 foo B 3 4
7 foo C 5 6
8 foo D 7 8
我尝试了以下方法:
temp = merge(master, cond_a, all.x=TRUE)
这给了我:
userid condition answer1 answer2
1 bar A 1 2
2 bar B <NA> <NA>
3 bar C <NA> <NA>
4 bar D <NA> <NA>
5 foo A 1 2
6 foo B <NA> <NA>
7 foo C <NA> <NA>
8 foo D <NA> <NA>
但是一旦我这样做了……
merge(temp, cond_b, all.x=TRUE)
条件B
没有值。怎么会?
userid condition answer1 answer2
1 bar A 1 2
2 bar B <NA> <NA>
3 bar C <NA> <NA>
4 bar D <NA> <NA>
5 foo A 1 2
6 foo B <NA> <NA>
7 foo C <NA> <NA>
8 foo D <NA> <NA>
【问题讨论】:
我刚刚注意到我可以做merge(temp, cond_b, all=TRUE)
,但这会给我额外的行,其中包含NA
s。不理想。
这会有帮助吗? temp <-rbind(cond_a,cond_b,cond_c,cond_d) temp[order(temp["userid"]),]
或者与master中的内容有什么特定的关系?
在这篇文章的简单案例中,确实如此!我在主数据集中有一些额外的列,这就是为什么它在我的特定数据集中不起作用的原因——但我没有提到这一点,所以也可以随意发布它作为示例。
【参考方案1】:
您可以使用Reduce()
和complete.cases()
,如下所示:
merged <- Reduce(function(x, y) merge(x, y, all=TRUE),
list(master, cond_a, cond_b, cond_c, cond_d))
merged[complete.cases(merged), ]
# userid condition answer1 answer2
# 1 bar A 1 2
# 2 bar B 3 4
# 4 bar C 5 6
# 6 bar D 7 8
# 8 foo A 1 2
# 9 foo B 3 4
# 11 foo C 5 6
# 13 foo D 7 8
Reduce()
可能需要一些时间来适应。您定义您的函数,然后提供对象的list
以重复应用该函数。因此,该语句就像在做:
temp1 <- merge(master, cond_a, all=TRUE)
temp2 <- merge(temp1, cond_b, all=TRUE)
temp3 <- merge(temp2, ....)
或者类似的东西:
merge(merge(merge(master, cond_a, all=TRUE), cond_b, all=TRUE), cond_c, all=TRUE)
complete.cases()
创建指定列是否“完整”的逻辑向量;此逻辑向量可用于从合并的data.frame
中提取子集。
【讨论】:
酷,这非常适合我的具体示例!现在,如果master
数据框包含我想保留的其他列,我该怎么办?基本上,我只想将答案分配给唯一的 userid
和 condition
对。
所以,更准确地说,我现在得到一行 foo, A, 1, 2, other
,但随后是 foo, B, <NA>, <NA>, blah
,这将在 complete.cases()
步骤中删除。
我认为我明白了。当我首先rbind
所有条件数据帧然后merge(master, all_conditions, all.x=TRUE)
时,这似乎给了我一切。【参考方案2】:
正如 OP 所说,鉴于与主数据框没有明确的关系,一个选项是这样的:
temp <-rbind(cond_a,cond_b,cond_c,cond_d)
temp[order(temp["userid"]),]
如果已知任何关系,可能会有一个不简单的解决方案。
【讨论】:
“显式关系”到底是什么意思?显然userid
和condition
是实验数据中的因子,而答案分数是属于某个用户和治疗的简单数字项。
我的意思是,即使没有主 df,也可以得到你想要的输出。所以只要 cond_[a-d] 就足够了。如果 master 和 cond_[a-d] 之间有更多的关系(比如那里的列),那么这可能不足以作为解决方案【参考方案3】:
您可以将此连接表示为SQL
语句,然后使用sqldf
库来执行它。
cond_all = rbind(cond_a, cond_b, cond_c, cond_d)
> sqldf('select p.userid as userid, p.condition as condition, answer1, answer2 from master as p join cond_all as q on p.userid=q.userid and p.condition=q.condition order by userid, condition')
userid condition answer1 answer2
1 bar A 1 2
2 bar B 3 4
3 bar C 5 6
4 bar D 7 8
5 foo A 1 2
6 foo B 3 4
7 foo C 5 6
8 foo D 7 8
您在评论中提到主数据帧具有 cond 数据帧中不存在的额外列。您应该能够修改此 SQL 查询,使其仍然适用于这种情况。
【讨论】:
以上是关于如何合并具有相同列名的多个数据框?的主要内容,如果未能解决你的问题,请参考以下文章
java - 如何在java中组合(连接)具有相同列名的两个数据框