【问题标题】:Replace rows in one data frame if they appear in another data frame如果它们出现在另一个数据框中,则替换一个数据框中的行
【发布时间】:2015-06-18 09:54:30
【问题描述】:

我有以下两个数据框:

df1

id   V1 V2 V3
210  4  NA 7
220  NA NA NA
230  2  0  1
240  4  NA NA
250  1  9  2
260  6  5  NA
270  0  NA 3

df2

id   V1 V2 V3
210  4  3  7
240  4  3  NA
270  0  3 3

df2 是 df1 在 V2 中具有 NA 并且在 V1 或 V3 中具有至少一个数值的所有实例。在这种情况下,我已将 V2 中的 NA 更改为“3”。

我现在想将这些 df 重新组合在一起。具体来说,我想替换 df1 中出现在 df2 中的所有行。我的预期输出是这样的:

id   V1 V2 V3
210  4  3 7
220  NA NA NA
230  2  0  1
240  4  3 NA
250  1  9  2
260  6  5  NA
270  0  3 3

我查看了this question,但它是根据 df 中的特定值执行此操作的。并且this question 通过指定要替换的实际值来类似地回答。我真正的 df 很大,我要做的就是将两个 df 放在一起,用 df2 替换出现在两者中的行。

【问题讨论】:

    标签: r


    【解决方案1】:

    一个简单的match 调用将识别与df1$id 内的df2$id 匹配的实例(按正确的出现顺序)将解决此问题

    df1[match(df2$id, df1$id), ] <- df2
    df1
    #    id V1 V2 V3
    # 1 210  4  3  7
    # 2 220 NA NA NA
    # 3 230  2  0  1
    # 4 240  4  3 NA
    # 5 250  1  9  2
    # 6 260  6  5 NA
    # 7 270  0  3  3
    

    编辑: 正如@plafort 指出的那样,您可以避免首先创建df2,但我会采用矢量化方法而不是使用apply。例如

    indx <- rowSums(is.na(df1)) != (ncol(df1) - 1) & is.na(df1$V2)
    df1[indx, "V2"] <- 3
    

    【讨论】:

    • 有没有办法用 dplyr 或 equiv 做到这一点?
    • @StephanieOwen 这个解决方案有什么问题?慢吗?读书难吗?换句话说,为什么工具比原因更重要?
    • 因为我的主管真的很烦人,并且出于某种原因痴迷于我们的实验室组使用 dplyr 库和函数进行所有编码,无论它是否有效。解决方案本身没有问题 dplyr 函数通常更具可读性
    • 这是我见过的最优雅的解决方案,因为它很简单。人们总是可以创建一个虚拟变量并在任务完成时将其删除。
    【解决方案2】:

    我的匹配语法类似于@DavidArenburg with

    df1[df1$id %in% df2$id, ] <- df2
    

    不必创建额外的数据框有帮助吗?如果正在创建df2 来填充df1,您可以快速将3 分配给适当的区域,而无需创建新的数据框。

    indx <- apply(df1, 1, function(x) is.na(x[3]) && any(!is.na(x[2:4])))
    df1$V2[indx] <- 3
    df1
       id V1 V2 V3
    1 210  4  3  7
    2 220 NA NA NA
    3 230  2  0  1
    4 240  4  3 NA
    5 250  1  9  2
    6 260  6  5 NA
    7 270  0  3  3
    

    【讨论】:

      【解决方案3】:

      如果有人需要使用 df1[match(dfid, dfid), ]

        df1$aux1<-paste(df1$id1,df1$id2) 
        df2$aux1<-paste(df2$id1,df2$id2) 
        df1[match(df2$aux1, df1$aux1), ] <- df2
        df1 <- df1[ , names(df1)!="aux1"]
      

      这可能很明显,并不优雅,但它确实有效

      【讨论】:

        猜你喜欢
        • 2012-06-26
        • 2021-12-31
        • 2017-11-28
        • 2021-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-09
        相关资源
        最近更新 更多