【问题标题】:Retrieve matching rows based on partial strings between two data frames根据两个数据帧之间的部分字符串检索匹配行
【发布时间】:2019-03-17 12:34:47
【问题描述】:

我正在寻找一种方法来根据另一个数据帧的标准从一个数据帧中检索行。这是我正在尝试做的一个说明性示例:-

prefix<-c("0141", "0142", "0143", "0144", "0156", "0157", "0158", "0161")
IDnumbers<-c("01416783902", "014138926949", "01444783002", "07862738468", "01618769203", "015728936482", "07728394562","07264783959","02873819364")
IDnames<-c("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii")

df1<-cbind(IDnames, IDnumbers)
df2<-cbind(prefix)

基本上,我试图通过将 4 位前缀与“IDnumbers”变量中的前 4 位数字相匹配来从我的 df 中检索行。我最终应该得到:-

aaa    01416783902
bbb    014138926949
ccc    01444783002
eee    01618769203
fff    015728936482

我尝试过的无法正常工作的代码是这样的:-

results<-sapply(df2$prefix, grep, df1$IDnumbers)

这没有返回所需的输出。我想在 dplyr 和 data.table 包中有解决方案,但我没有找到任何解决方案。任何建议都将受到欢迎!干杯:)

【问题讨论】:

    标签: r dplyr data.table match


    【解决方案1】:

    一种方法是将pastedf2 中的prefix 放在一个字符串中,并将subset 中的行与df1 匹配该模式。

    subset(df1, grepl(paste0("^",df2$prefix, collapse = "|"), IDnumbers))
    
    #  IDnames    IDnumbers
    #1     aaa  01416783902
    #2     bbb 014138926949
    #3     ccc  01444783002
    #5     eee  01618769203
    #6     fff 015728936482
    

    作为参考,paste0 语句生成的模式是

    paste0("^",df2$prefix, collapse = "|")
    #[1] "^0141|^0142|^0143|^0144|^0156|^0157|^0158|^0161"
    

    因此它会过滤IDnumbers 以这些数字中的任何一个开头的行。

    数据

    更改了数据的格式,使其成为数据框而不是矩阵。

    prefix<-c("0141", "0142", "0143", "0144", "0156", "0157", "0158", "0161")
    IDnumbers<-c("01416783902", "014138926949", "01444783002", "07862738468", 
          "01618769203", "015728936482", "07728394562","07264783959","02873819364")
    IDnames<-c("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii")
    
    df1<-data.frame(IDnames, IDnumbers, stringsAsFactors = FALSE)
    df2<-data.frame(prefix, stringsAsFactors = FALSE)
    

    【讨论】:

      【解决方案2】:

      在得到'IDnumbers'的substring 之后,我们可以使用精确匹配的%in% 来得到一个逻辑向量

      subset(df1, substr(IDnumbers, 1, 4) %in% df2$prefix)
      #   IDnames    IDnumbers
      #1     aaa  01416783902
      #2     bbb 014138926949
      #3     ccc  01444783002
      #5     eee  01618769203
      #6     fff 015728936482
      

      stringr 1.4.0 版本开始,我们也可以使用str_starts/str_ends

      library(dplyr)
      library(stringr)
      df1 %>% 
          filter(str_starts(IDnumbers, paste(df2$prefix, collapse="|")))
      # IDnames    IDnumbers
      #1     aaa  01416783902
      #2     bbb 014138926949
      #3     ccc  01444783002
      #4     eee  01618769203
      #5     fff 015728936482
      

      【讨论】:

      • 这个解决方案效果很好,尤其是stringr 解决方案。非常感谢!! :)
      猜你喜欢
      • 2020-11-28
      • 1970-01-01
      • 1970-01-01
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 2019-08-23
      • 1970-01-01
      • 2019-02-15
      相关资源
      最近更新 更多