结合使用grepl和粘贴来匹配非常大的数据集的子字符串

时间:2019-03-03 00:13:56

标签: r

我有一个列向量Item_A,包含大约150,000个观察值(1个列变量),另一个列向量Item_B,包含650个观察值。 如果Item_B中存在一个单词字符串,Item_A中将有一个列输出TRUE

使用解决方案在Item_B内的Item_A中搜索子字符串,并给出一个带有TRUEFALSE的向量,建议使用以下代码:

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

greplpaste结合使用,但前提是Item_B是较小的向量。我首先尝试在Item_B中仅使用20个观察值,并且它运行良好。 不幸的是,当我尝试使用Error in grepl(paste(Item_B, collapse = "|"), Item_A) :的652个观测值矢量时,我得到了错误:Item_B

您有什么建议使其适用于大向量?

这就是我希望输出的样子:

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 :(得分:2)

在我的模拟示例中,使用stringi的速度比grepl快50倍:

# 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值。