【问题标题】:identify observations based on 2 elements in 2 dataframes that do not match [duplicate]根据 2 个数据框中不匹配的 2 个元素识别观察结果 [重复]
【发布时间】:2021-03-19 06:32:04
【问题描述】:

我想使用 2 个指标(id 和日期)识别 1 个 df 中与另一个 df 不匹配的观察值。下面是示例 df1 和 df2。

df1
id       date          n
12-40   12/22/2018     3
11-08   10/02/2016     11
df2
id       date          interval
12-40   12/22/2018     3
11-08   10/02/2016     32
22-22   11/10/2015     11

我想要一个 df 输出 df2 中的行,而不是 df1 中的行,就像这样。请注意,df2 的第 3 行(基于 id 和日期)不在 df1 中。

df3
id       date          interval
22-22   11/10/2015     11

我尝试在 tidyverse 中执行此操作,但无法使代码正常工作。有人对如何执行此操作有建议吗?

【问题讨论】:

    标签: r dataframe tidyverse


    【解决方案1】:

    我们可以使用tidyverse 中的anti_join(正如OP 提到的与tidyverse 一起工作)。在这里,我们使用 OP 帖子中提到的“id”和“日期”。更复杂的连接可以使用tidyverse

    library(dplyr)
    anti_join(df2, df1, by = c('id', 'date'))
    #     id       date interval
    #1 22-22 11/10/2015       11
    

    或与data.table 类似的选项,它应该非常有效

    library(data.table)
    setDT(df2)[!df1, on = .(id, date)]
    #      id       date interval
    #1: 22-22 11/10/2015       11
    

    数据

    df1 <- structure(list(id = c("12-40", "11-08"), date = c("12/22/2018", 
    "10/02/2016"), n = c(3L, 11L)), class = "data.frame", row.names = c(NA, 
    -2L))
    
    df2 <- structure(list(id = c("12-40", "11-08", "22-22"), date = c("12/22/2018", 
    "10/02/2016", "11/10/2015"), interval = c(3L, 32L, 11L)), class = "data.frame",
    row.names = c(NA, 
    -3L))
    

    【讨论】:

      【解决方案2】:

      试试这个(两个选项都是base R,遵循 OP 指示,不需要任何包):

      #Code1
      df3 <- df2[!paste(df2$id,df1$date) %in% paste(df1$id,df2$date),]
      

      输出:

           id       date interval
      3 22-22 11/10/2015       11
      

      也可以考虑:

      #Code 2
      df3 <- subset(df2,!paste(id,date) %in% paste(df1$id,df1$date))
      

      输出:

           id       date interval
      3 22-22 11/10/2015       11
      

      使用的一些数据:

      #Data1
      df1 <- structure(list(id = c("12-40", "11-08"), date = c("12/22/2018", 
      "10/02/2016"), n = c(3L, 11L)), class = "data.frame", row.names = c(NA, 
      -2L))
      
      #Data2
      df2 <- structure(list(id = c("12-40", "11-08", "22-22"), date = c("12/22/2018", 
      "10/02/2016", "11/10/2015"), interval = c(3L, 32L, 11L)), class = "data.frame", row.names = c(NA, 
      -3L))
      

      【讨论】:

        【解决方案3】:

        另一个使用 merge + subset + complete.cases 的基本 R 选项

        df3 <- subset(
          u <- merge(df1, df2, by = c("id", "date"), all.y = TRUE),
          !complete.cases(u)
        )[names(df2)]
        

        给了

        > df3
             id       date interval
        3 22-22 11/10/2015       11
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-25
          • 2013-07-12
          • 2017-05-24
          • 2020-11-08
          • 2018-07-05
          • 2013-11-23
          • 2022-08-12
          • 1970-01-01
          相关资源
          最近更新 更多