R поиск строковых шаблонов вектора в элементах другого (по парам)

#r #vector

#r #вектор

Вопрос:

У меня есть вектор символов

 c1 <- c("BEL","BEL","BEL","BEL")
 

и другой символьный вектор той же длины

 c2 <- c(" BEL-65_DRe-I_1p:BEL;_LTR_Retrotransposon;_Transposable_Element;_Nonautonomous;_BEL-65_DRe-I", "L1-2_NN_3p:L1;_Non-LTR_Retrotransposon;_Transposable_Element;_L1-2_NN", "BEL-13_CQ-I_1p:BEL;_LTR_Retrotransposon;_Transposable_Element;_BEL-13_CQ_;_BEL-13_CQ-LTR;_BEL-13_CQ-I", "BEL-31_CQ-I_1p:BEL;_LTR_Retrotransposon;_Transposable_Element;_BEL-31_CQ_;_BEL-31_CQ-LTR;_BEL-31_CQ-I", "Gypsy-22_CQ-I_1p:Gypsy;_LTR_Retrotransposon;_Transposable_Element;_Gypsy-22_CQ_;_Gypsy-22_CQ-LTR;_Gypsy-22_CQ-I")
 

Я хочу знать, найдена ли каждая строка в c1 c2 с тем же индексом (игнорируя регистр), т. Е. Если c1[1] найдена в c2[1] , c1[2] в c2[2] и так далее.
На практике векторы могут содержать миллионы элементов.

Мое текущее решение

 test <- Map(function(x,y) grepl(x,y, ignore.case = T), c1, c2)
 

Но он не векторизован, следовательно, относительно медленный.
Есть ли лучшее решение?

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

1. Вы пробовали library(stringi);c1 <- stri_rand_strings(1e6, 2);c2 <- paste0(stri_rand_strings(1e6, 20), tolower(c1));system.time(res <- stri_detect(c2, fixed = c1, case_insensitive = TRUE)) ?

2. Спасибо! Я знал, что должна быть специальная функция. У меня даже уже был установлен stringi, но в нем так много функций, что трудно найти ту, которая вам нужна. Вы можете опубликовать этот ответ, чтобы я его проверил.

3. Конечно, только что сделал это.

Ответ №1:

Это выполняется довольно быстро:

 library(stringi)
c1 <- stri_rand_strings(1e6, 2)
c2 <- paste0(stri_rand_strings(1e6, 20), tolower(c1))
system.time(res <- stri_detect(c2, fixed = c1, case_insensitive = TRUE))
       # User      System verstrichen 
       # 0.73        0.00        0.75
 

Отчасти потому, что я проверял не шаблон регулярного выражения, а константу string ( fixed ) , которую вы также можете использовать grep* .

Ответ №2:

Вы могли бы попробовать следующее, используя пакет stringr:

 require(stringr)
require(data.table)

data <- data.table(c1, c2)
data[, FOUND:= str_detect(toupper(c2), toupper(c1))]
 

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

1. Спасибо, это должно работать так же хорошо, как stringi и решение.

2. Да, я думаю, что это примерно то же самое.

Ответ №3:

Что будет работать так же хорошо, как и ваши решения, так это использовать apply . Для этого небольшого примера это работает хорошо, если это будет быстрее для больших данных, я не знаю.

 apply(rbind(c1,c2), 2, function(y){grepl(pattern = y[1],x=y[2], ignore.case = T)})
[1]  TRUE FALSE  TRUE  TRUE FALSE 
 

Отредактировано:
Мне пришлось добавить еще один «BEL», чтобы заставить его работать, потому что ваш c1 состоит из 4 элементов, а c2 из 5

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

1. спасибо, я думаю, это должно работать так же хорошо, как Map() и то, что они оба полагаются на for внутренние циклы.