Если вам нужно только обновить столбец оценки, я рекомендую использовать stringi::stri_detect_regex
:
# stringi.regex
neg.sent.dictionary$scored <-
stringi::stri_detect_regex(text, neg.sent.dictionary$pattern) | neg.sent.dictionary$scored
Однако, если вам нужно изменить text
и обновить оценку Вы можете изменить text
с Внутренним gsub в пределах l oop, что немного быстрее. Но вынуждает вас проверять все аргументы вне функции:
# internal.gsub
p <- neg.sent.dictionary$pattern
r <- neg.sent.dictionary$replacement
for(i in 1:NROW(neg.sent.dictionary))
text <- .Internal(gsub(p[i], r[i], text, F, F, F, F))
Я предлагаю все же для l oop, так как семейство * apply обычно одинаково эффективно, или медленнее по сравнению с for для l oop.
После изменения text
вместо него можно использовать stringi::stri_detect_fixed
, так как он может соответствовать намного быстрее по сравнению с версия регулярного выражения:
# stringi.fixed
neg.sent.dictionary$scored <-
stringi::stri_detect_fixed(text, neg.sent.dictionary$feature) | neg.sent.dictionary$scored
Я запустил несколько микробенчмарков, чтобы проверить производительность нескольких подходов. Я тестировал их в 4 различных сценариях ios:
- Маленький текст, Маленький словарь
- Большой текст, Маленький словарь
- Маленький текст, Большой словарь
- Большой текст, Большой словарь
Рекомендуемые решения называются stringi.regex
, internal.gsub
и stringi.fixed
соответственно. Вот мои настройки:
library(tidyverse)
text <- "123 \"StackOverflow\""
neg.sent.dictionary <- tibble(
pattern=c("\\d+", "true|false|null", "\"\\w+\""),
replacement=c("number", "boolean", "string"),
feature=c("number", "boolean", "string"),
scored=F
)
# Small
bigger.text <- text
# Bigger
bigger.text <- paste(rep(text, 1e4), collapse=" ")
# Small
bigger.nsd <- neg.sent.dictionary
# Bigger
bigger.nsd <- bind_rows(rep(list(neg.sent.dictionary), 1e3))
microbenchmark::microbenchmark(
internal.gsub={
p = bigger.nsd$pattern
r = bigger.nsd$replacement
for(i in 1:NROW(bigger.nsd))
.Internal(gsub(p[i], r[i], bigger.text, F, F, F, F))
},
gsub={
for (i in 1:nrow(bigger.nsd)){
gsub(bigger.nsd$pattern[i], bigger.nsd$replacement[i], bigger.text, fixed = FALSE)
}
},
unit="u"
)
p = bigger.nsd$pattern
r = bigger.nsd$replacement
for(i in 1:NROW(bigger.nsd))
bigger.text.2 = .Internal(gsub(p[i], r[i], bigger.text, F, F, F, F))
microbenchmark::microbenchmark(
stringi.regex={
stringi::stri_detect_regex(bigger.text, bigger.nsd$pattern) | bigger.nsd$scored
},
stringi.fixed={
stringi::stri_detect_fixed(bigger.text.2, bigger.nsd$feature) | bigger.nsd$scored
},
for.loop.internal.grepl={
f = bigger.nsd$feature
s = bigger.nsd$scored
for (i in 1:nrow(bigger.nsd))
.Internal(grepl(f[i], bigger.text.2, F, F, F, T, F, F)) | s[i]
},
for.loop.ifelse={
for (i in 1:nrow(bigger.nsd)){
ifelse(grepl(bigger.nsd$pattern[i], bigger.text.2, fixed = TRUE), TRUE, bigger.nsd$scored[i])
}
},
unit="u"
)
А вот и результаты:
# 1. Small text, Small dictionary
Unit: microseconds
expr min lq mean median uq max neval cld
internal.gsub 2566.4 2711.10 3058.682 2823.70 3038.30 10098.0 100 a
gsub 2703.3 2846.45 3331.547 2956.55 3288.55 18270.4 100 a
Unit: microseconds
expr min lq mean median uq max neval cld
stringi.regex 68.3 83.65 103.597 100.25 114.30 219.3 100 a
stringi.fixed 9.8 13.75 24.321 25.35 32.05 49.6 100 a
for.loop.internal.grepl 3029.7 3302.40 3721.852 3485.95 3803.45 10038.2 100 b
for.loop.ifelse 3010.8 3317.50 3777.069 3547.45 3918.30 8917.9 100 b
# 2. Bigger text, Small dictionary
Unit: microseconds
expr min lq mean median uq max neval cld
internal.gsub 18934.6 20265.15 22315.87 20908.40 22121.30 70715.8 100 a
gsub 19726.7 20593.55 22239.65 21181.75 21998.85 36940.8 100 a
Unit: microseconds
expr min lq mean median uq max neval cld
stringi.regex 1140.4 1222.35 1473.995 1268.40 1470.30 3142.4 100 b
stringi.fixed 193.5 209.40 271.207 225.75 257.20 2642.2 100 a
for.loop.internal.grepl 3825.5 4102.20 4997.894 4437.90 5316.70 11796.2 100 c
for.loop.ifelse 4174.0 4419.95 5001.795 4662.15 5059.05 8682.3 100 c
# 3. Small text, Bigger dictionary
Unit: microseconds
expr min lq mean median uq max neval cld
internal.gsub 32073.3 33212.40 36108.31 34489.55 37420.65 57649.1 100 a
gsub 42647.7 44619.95 48733.21 46908.30 50926.50 67080.3 100 b
Unit: microseconds
expr min lq mean median uq max neval cld
stringi.regex 53773.7 54816.20 57261.168 55394.05 57517.45 80971.4 100 d
stringi.fixed 284.6 326.45 361.985 337.60 369.25 705.2 100 a
for.loop.internal.grepl 7792.3 8316.00 8881.116 8613.40 8957.30 16013.8 100 b
for.loop.ifelse 17276.4 18438.95 20272.754 19306.30 22309.25 34873.0 100 c
# 4. Bigger text, Bigger dictionary
Unit: microseconds
expr min lq mean median uq max neval cld
internal.gsub 16483350 17148515 17897795 17713030 18624919 20713810 100 a
gsub 16550789 17180693 18020193 17772800 18714014 21618478 100 a
Unit: microseconds
expr min lq mean median uq max neval cld
stringi.regex 1089151.1 1104097.2 1281581.9 1140744.2 1302083.6 2350601.5 100 c
stringi.fixed 195208.3 198095.9 202585.5 201291.5 206144.1 230414.8 100 a
for.loop.internal.grepl 781006.4 791378.0 982425.3 817768.6 892169.8 2090793.6 100 b
for.loop.ifelse 1110029.5 1132167.4 1356409.4 1161535.1 1230636.3 3058030.2 100 c