通过ID合并R中的两个数据帧,一个是另一个的子集

通过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

我在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结构

数据格式:

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"]