通过ID合并R中的两个数据帧,一个是另一个的子集
我在R中有两个数据帧:“dfold”有175个变量,“dfnew”有75个变量。两个数据帧由主键(即“pid”)匹配。dfnew是dfold的子集,因此dfnew中的所有变量也在dfold上,但具有更新的插补值(不再有NAs)。同时,dfold有更多的变量,我将在分析阶段需要它们。我希望在dfmerge中合并2个数据帧,以便从dfnew-->dfold更新公共变量,但同时保留dfold中预先存在的变量。我尝试了merge()、match()、dplyr和sqldf包,但要么我获得了只包含更新的75个变量的dfmerge(左连接),要么获得了包含250个变量的dfmerge(包含NAs的旧变量和不包含它们的新变量共存)。我发现的唯一方法(这里)是一个优雅但相当长的(10行)循环,它在通过pid合并all.x=TRUE选项后消除了*.x变量。如果可以的话,请您提供一个更有效的方法来获得这样的结果 先谢谢你 附言:为了让事情变得更简单,我创建了dfold和dfnew的最小版本:dfnew现在有3个变量,没有NAs,而dfold有5个变量,包括NAs。这里是dataframes结构 数据格式:通过ID合并R中的两个数据帧,一个是另一个的子集,r,dataframe,merge,R,Dataframe,Merge,我在R中有两个数据帧:“dfold”有175个变量,“dfnew”有75个变量。两个数据帧由主键(即“pid”)匹配。dfnew是dfold的子集,因此dfnew中的所有变量也在dfold上,但具有更新的插补值(不再有NAs)。同时,dfold有更多的变量,我将在分析阶段需要它们。我希望在dfmerge中合并2个数据帧,以便从dfnew-->dfold更新公共变量,但同时保留dfold中预先存在的变量。我尝试了merge()、match()、dplyr和sqldf包,但要么我获得了只包含更新的7
structure(list(Country = structure(c(1L, 3L, 2L, 3L, 2L), .Label = c("France",
"Germany", "Spain"), class = "factor"), Age = c(44L, 27L, 30L,
38L, 40L), Salary = c(72000L, 48000L, 54000L, 61000L, NA), Purchased = structure(c(1L,
2L, 1L, 1L, 2L), .Label = c("No", "Yes"), class = "factor"),
pid = 1:5), .Names = c("Country", "Age", "Salary", "Purchased",
"pid"), row.names = c(NA, 5L), class = "data.frame")
dfnew:
structure(list(Age = c(44, 27, 30), Salary = c(72000, 48000,
54000), pid = c(1, 2, 3)), .Names = c("Age", "Salary", "pid"), row.names = c(NA,
3L), class = "data.frame")
虽然这里的问题仅限于2个变量,但请注意,实际情况将涉及75个变量 好的,这个解决方案假设您实际上不需要合并,只想用
dfnew
中的插补值更新dfold
中的NA
值
> dfold
Country Age Salary Purchased pid
1 France NA 72000 No 1
2 Spain 27 48000 Yes 2
3 Germany 30 54000 No 3
4 Spain 38 61000 No 4
5 Germany 40 NA Yes 5
> dfnew
Age Salary pid
1 44 72000 1
2 27 48000 2
3 30 54000 3
4 38 61000 4
5 40 70000 5
要对单个列执行此操作,请尝试
dfold$Salary <- ifelse(is.na(dfold$Salary), dfnew$Salary[dfnew$pid == dfold$pid], dfold$Salary)
> dfold
Country Age Salary Purchased pid
1 France NA 72000 No 1
2 Spain 27 48000 Yes 2
3 Germany 30 54000 No 3
4 Spain 38 61000 No 4
5 Germany 40 70000 Yes 5
现在使用mapply
将NA
值替换为ifelse
:
dfold[,cols] <- mapply(function(x, y) ifelse(is.na(x), y[dfnew$pid == dfold$pid], x), dfold[,cols], dfnew[,cols])
> dfold
Country Age Salary Purchased pid
1 France 44 72000 No 1
2 Spain 27 48000 Yes 2
3 Germany 30 54000 No 3
4 Spain 38 61000 No 4
5 Germany 40 70000 Yes 5
你能提供一些有意义的样本数据吗?可能每个数据帧中有10行,其中有5个公共变量,在dfold子样本中还有5个其他变量?我们当然很乐意这样做,但不知道如何在这里附加数据,有什么提示吗?最好的方法是对上面解释的子集使用
dput()
命令,类似于dput(dfold[1:10,1:10])
和dput(dfnew[1:10,1:5])
(您可能需要更改列索引以获得5个常用变量和5个不常用变量)。然后将R
控制台(通常以结构(…
)的输出粘贴到您的问题文本中。在原始帖子中编辑,谢谢:)我刚刚让事情变得更简单了,但dfold和dfnew应该仍然有效。我将自己重新创建它,但最理想的是dfnew
应该包括所有5行,尤其是naa
列中的Salary
值。很棒的优雅解决方案,刚刚在整个真实数据集上进行了测试,工作起来就像一个champ:)只是为了适当地结束主题并供将来参考:在您看来,合并或联接查询不能执行相同的操作?在提到有关Stackoverflow的不同问题后,我非常确定,这不能通过简单的合并或联接来完成。您可能需要事先定义要覆盖的单元格,或者删除.x
/.y
变量,这些变量在之后不必要地创建。完美,事实上,我在原始帖子中提到的循环就是:删除合并后创建的.x(不必要的)。再次感谢您花费的时间和支持。
dfold[,cols] <- mapply(function(x, y) ifelse(is.na(x), y[dfnew$pid == dfold$pid], x), dfold[,cols], dfnew[,cols])
> dfold
Country Age Salary Purchased pid
1 France 44 72000 No 1
2 Spain 27 48000 Yes 2
3 Germany 30 54000 No 3
4 Spain 38 61000 No 4
5 Germany 40 70000 Yes 5
cols <- names(dfnew)[which(names(dfnew) %in% names(dfold))][names(dfnew) != "pid"]