在R中基于另一个数据框替换数据框中的值

17
在下面的示例中,userids 是我的参考数据框,userdata 是应进行替换的数据框。
> userids <- data.frame(USER=c('Ann','Jim','Lee','Bob'),ID=c(1,2,3,4))
> userids
  USER ID
1  Ann  1
2  Jim  2
3  Lee  3
4  Bob  4

> userdata <- data.frame(INFO=c('foo','bar','foo','bar'), ID=c('Bob','Jim','Ann','Lee'),AGE=c('43','33','53','26'), FRIENDID=c('Ann',NA,'Lee','Jim'))
> userdata
  INFO  ID AGE FRIENDID
1  foo Bob  43      Ann
2  bar Jim  33       NA
3  foo Ann  53      Lee
4  bar Lee  26      Jim

我该如何将userdata中的ID和FRIENDID替换为userids中与USER对应的ID?
期望输出结果:
  INFO  ID AGE FRIENDID
1  foo   4  43        1
2  bar   2  33       NA
3  foo   1  53        3
4  bar   3  26        2

“正确”是什么意思?您想将 userids$USERuserdata$ID 匹配吗? - Richie Cotton
1
我猜测correct应该是对应的(corresponding) - Arun
@Robert,提供期望的输出将有助于避免这些混淆(下次)。 - Arun
4个回答

25
使用 match
userdata$ID <- userids$ID[match(userdata$ID, userids$USER)]
userdata$FRIENDID <- userids$ID[match(userdata$FRIENDID, userids$USER)]

2
这是一种可能性:
library(qdap)
userdata$FRIENDID <- lookup(userdata$FRIENDID, userids)
userdata$ID <- lookup(userdata$ID, userids)

或者赢得一行奖励:
userdata[, c(2, 4)] <- lapply(userdata[, c(2, 4)], lookup, key.match=userids)

qdap看起来非常棒,但我在我的软件源中找不到它。 - N8TRO
1
不确定为什么。也许是因为它是一个较新的版本。尝试使用install.packages("qdap")或者你可以使用:library(devtools) install_github("qdap", "trinker")来获取开发版本。 - Tyler Rinker
失败。错误:依赖项'openNLP'对于'qdap'软件包不可用。 - N8TRO
@TylerRinker 这只返回朋友的ID。也许你需要调用它两次。 - agstudy
2
@agstudy。我错过了那个。你是正确的。我已经编辑过来反映这一点了。 - Tyler Rinker
显示剩余2条评论

0

这里有一个可能的解决方案,它也适用于每个ID具有多个记录的数据集,尽管我们需要先将ID和FRIENDID变量强制转换为字符:

> userdata$ID <- sapply(userdata$ID, function(x){gsub(x, userids[userids$USER==x, 2], x)})
> userdata$FRIENDID <- sapply(userdata$FRIENDID, function(x){gsub(x, userids[userids$USER==x, 2], x)})

0

这里尝试使用sqldf来获取不同列的多重连接结果。

  library(sqldf)
  sqldf('SELECT d.INFO,d.AGE,i1.ID ,i2.ID FRIENDID
       FROM 
       userdata d
       INNER JOIN 
       userids i1 ON (i1.USER=d.FRIENDID)
       INNER JOIN
        userids i2 ON (i2.USER=d.ID)')

 INFO AGE ID FRIENDID
1  foo  43  1        4
2  foo  53  3        1
3  bar  26  2        3

但是这会删除NA行!也许有人可以建议我如何处理NA!

编辑

感谢G. Grothendieck的评论,将INNER替换为LEFT,我们得到了结果。

 sqldf('SELECT d.INFO,d.AGE,i1.ID ,i2.ID FRIENDID
        FROM 
        userdata d
        LEFT JOIN 
        userids i1 ON (i1.USER=d.FRIENDID)
        LEFT JOIN
         userids i2 ON (i2.USER=d.ID)')
INFO AGE ID FRIENDID
1  foo  43  1        4
2  bar  33 NA        2
3  foo  53  3        1
4  bar  26  2        3

1
关于您的问题,请将两个 INNER 实例替换为 LEFT - G. Grothendieck

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