【问题标题】:Match values between R dataframes without using a for-loop在不使用 for 循环的情况下匹配 R 数据帧之间的值
【发布时间】:2021-06-09 13:28:03
【问题描述】:

我有以下数据框:

db1 = data.frame(name = c('a', 'b', 'c', 'd'), age = c('10', '20', '30', '40'), tier = NA)
db2 = data.frame(name = c('a', 'a', 'c', 'b'), age = c('10', '10', '30', '20'), tier = c('1', '3', '4', '2'))

如果nameage 变量匹配,我想将db2 中的tier 值输入到db1 的同一列中。

我可以使用 for 循环来做到这一点,但是当我们处理数千行时,这需要的时间太长了。有没有更快的方法来做到这一点?

for (i in 1:nrow(db1)){
  for (j in 1:nrow(db2)){
    if (db1$name[i] == db2$name[j] & db1$age[i] == db2$age[j]){
      db1$tier[i] = db2$tier[j]
    }
  }
}

【问题讨论】:

  • db1 (db1$tier <- NULL) 中删除tier 列。这将是一个简单的 mergemerge(db1, db2) 或者更具体的 - merge(db1, db2, by = c('name', 'age'))
  • 这行得通,谢谢。如果您发布答案,那么我会接受它
  • 匹配两次怎么办?在你的情况下name=aage=10?拿第一个?

标签: r for-loop


【解决方案1】:

first 如果它 匹配多次 也可以(您的代码采用最后一个),您可以使用 match 并使用 @ 用于多个列987654322@.

db1$tier <- db2$tier[match(interaction(db1[c("name","age")]),
                           interaction(db2[c("name","age")]))]
db1
#  name age tier
#1    a  10    1
#2    b  20    2
#3    c  30    4
#4    d  40 <NA>

或者使用另外的 `rev.

db1$tier <- rev(db2$tier)[match(interaction(db1[c("name","age")]),
                    rev(interaction(db2[c("name","age")])))]
db1
#  name age tier
#1    a  10    3
#2    b  20    2
#3    c  30    4
#4    d  40 <NA>

【讨论】:

  • 谢谢!我之前没有遇到过interaction()
【解决方案2】:

删除tier 列并使用merge -

db1$tier <- NULL
merge(db1, db2)

#  name age tier
#1    a  10    1
#2    a  10    3
#3    b  20    2
#4    c  30    4

如果您想在最终输出中使用 d,请使用 all.x = TRUE -

merge(db1, db2, all.x = TRUE)

#  name age tier
#1    a  10    1
#2    a  10    3
#3    b  20    2
#4    c  30    4
#5    d  40 <NA>

【讨论】:

    【解决方案3】:

    我们可以像下面这样使用merge + duplicated

    subset(
      merge(db1, db2, by = c("name", "age"), all.x = TRUE),
      !duplicated(cbind(name, age)),
      select = -tier.x
    )
    

    给你

      name age tier.y
    1    a  10      1
    3    b  20      2
    4    c  30      4
    5    d  40   <NA>
    

    【讨论】:

      【解决方案4】:

      这是一个简单的连接。

      library(dplyr)
      db3<-full_join(db2,db1, by = c("name" = "name", "age" = "age"), suffix = c("", ".x"))
      
        name age tier tier.x
      1    a  10    1     NA
      2    a  10    3     NA
      3    c  30    4     NA
      4    b  20    2     NA
      5    d  40 <NA>     NA
      
      ### i am assuming you want to have tier from db2 shown if they are not all NAs otherwise you can just drop before the join ###
      
      db3$tier.x = NULL
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-25
        • 1970-01-01
        • 2020-03-15
        • 1970-01-01
        • 1970-01-01
        • 2015-05-26
        • 2018-09-29
        • 2018-10-26
        相关资源
        最近更新 更多