如何合并具有相同列名的多个数据框?

9

我的情况:

我有一个“主”数据框,其中包含以下列:

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的行。不是很理想。 - slhck
这个有用吗? temp <-rbind(cond_a,cond_b,cond_c,cond_d) temp[order(temp["userid"]),] 还是说有什么特定的与主内容相关的关系吗? - A_K
在这篇文章的简单情况下,确实如此!我的主表中有一些额外的列,这就是为什么它在我的特定数据集中无法工作的原因 - 但我没有提到,所以请随意将其发布为示例。 - slhck
3个回答

12
你可以按照以下方式使用 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”对。 - slhck
所以,更准确地说,我现在得到了一行foo,A,1,2,other,但随后是foo,B,<NA>,<NA>,blah,这将在complete.cases()步骤中被删除。 - slhck
认为我搞定了。当我首先使用rbind合并所有条件数据框,然后再使用merge(master, all_conditions, all.x=TRUE),这似乎给了我所有的东西。 - slhck

2

根据原帖所述,考虑到没有与主数据框的明确关系,一个选项是:

temp <-rbind(cond_a,cond_b,cond_c,cond_d)
temp[order(temp["userid"]),]

也许如果我们知道任何关系,就能找到一个不那么简单的解决方案。

“明确关系”是什么意思?显然,“userid”和“condition”是实验数据的因素,而答案分数是属于某个用户和治疗方法的简单数字项。 - slhck
我的意思是即使没有主数据框,也可以得到您想要的输出。因此,只需使用cond_[a-d]即可。如果主数据框和cond_[a-d]之间存在更多关系(例如列),则这可能不足以作为解决方案。 - A_K

1
您可以将此连接表达为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

您在评论中提到主数据框具有不存在于条件数据框中的额外列。您应该能够修改此SQL查询以使其适用于此情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接