Извлекать совпадающие строки на основе частичных строк между двумя фреймами данных

#r #dplyr #data.table #match

#r #dplyr #данные.таблица #сопоставление

Вопрос:

Я ищу способ извлекать строки из одного фрейма данных на основе критериев из другого фрейма данных. Вот наглядный пример того, что я пытаюсь сделать:-

 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)
  

По сути, я пытаюсь извлечь строки из моего df, сопоставляя 4-значные префиксы с первыми 4 цифрами в переменной «IDnumbers». В итоге я должен получить:-

 aaa    01416783902
bbb    014138926949
ccc    01444783002
eee    01618769203
fff    015728936482
  

Код, который я пробовал, но который не сработал должным образом, заключается в следующем:-

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

Это не вернуло желаемый результат. Я полагаю, что в пакете dplyr и data.table есть решения, но я их не нашел. Любые предложения будут приветствоваться! Приветствия 🙂

Ответ №1:

Одним из способов является paste prefix из df2 в одной строке и 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:

Мы можем просто использовать %in% с точным совпадением, чтобы получить логический вектор после получения substr ввода ‘IDnumbers’

 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
  

Комментарии:

1. Это решение сработало действительно хорошо, особенно stringr решение. Большое вам спасибо !! 🙂