Использование grepl с пастой для сопоставления подстроки очень большого набора данных - PullRequest
0 голосов
/ 03 марта 2019

У меня есть вектор-столбец Item_A с около 150 000 наблюдений (переменная 1 столбец) и еще один вектор-столбец Item_B с 650 наблюдениями.Если строка из одного слова в Item_B присутствует в Item_A, столбец должен вывести TRUE.

Используя решения для поиска подстроки в Item_B в Item_A и указав векторс TRUE или FALSE был предложен следующий код:

  answer <-  grepl(paste(Item_B, collapse = "|"), Item_A)

grepl в сочетании с paste работает, но только если Item_B - это меньший вектор.Я сначала попробовал только с 20 наблюдениями в Item_B, и это прекрасно работает.К сожалению, я получаю ошибку: Error in grepl(paste(Item_B, collapse = "|"), Item_A) :, когда я пытаюсь использовать мой Item_B вектор 652 наблюдений.

Есть ли у вас какие-либо предложения, чтобы он работал для больших векторов?

Этокак я надеюсь, что мой вывод выглядит так:

Item_A          Item_B         Output_X
cri               bat             TRUE
sug               cri             FALSE
cri ird            NA             TRUE
sure bat           NA             TRUE
dev dev            NA             FALSE
batsman            NA             TRUE

1 Ответ

0 голосов
/ 03 марта 2019

Используя stringi, в моем смоделированном примере он работает почти в 50 раз быстрее, чем grepl:

# sample data
set.seed(47)
a = replicate(150000, sample(letters, size = 6))
b = replicate(600, sample(letters, size = 3))

big_pat = paste(b, collapse = "|")
ans_stringi = stri_detect_regex(a, big_pat)
ans_grepl = grepl(pattern = big_pat, x = a)
identical(ans_stringi, ans_grepl)
# [1] TRUE

# timing comparison
microbenchmark::microbenchmark(
  stringi = stri_detect_regex(a, big_pat),
  grepl = grepl(pattern = big_pat, x = a),
  times = 10L
)
# Unit: milliseconds
#     expr        min         lq       mean     median         uq        max neval
#  stringi   344.5289   348.7399   404.7191   409.6438   443.1995   477.3867    10
#    grepl 17323.6438 18743.7462 19058.1780 19192.0434 20012.5553 20061.1821    10

Альтернативой без регулярных выражений является использование fixed шаблонов и выполнение одного grepl за b пункт.Но я обнаружил, что это намного медленнее, чем приведенное выше решение.

ans_fixed = apply(sapply(Item_B, grepl, x = Item_A, fixed = TRUE), MAR = 1, FUN = any)

Использование fixed = TRUE сделает каждый grepl очень быстрым, но их все еще много, и он создает большое (length(a) на length(b)) матрица для результатов, которая могла бы съесть много памяти.В моем тестировании grepl был быстрее, чем stri_detect_fixed здесь.

Если у вас проблемы с памятью, делайте это порциями, скажем, 100 Item_B значений за раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...