【发布时间】:2019-04-04 15:51:43
【问题描述】:
我正在尝试计算 100,000 个字符串向量中每个字符串的非字母数字字符数。我发现我当前的实现比我想要的要慢。
我当前的实现使用purrr::map() 映射一个自定义函数,该函数使用stringr 包覆盖向量中的每个字符串。
library(dplyr)
library(stringr)
library(purrr)
# custom function that accepts string input and counts the number
# of non-alphanum characters
count_non_alnum <- function(x) {
stringr::str_detect(x, "[^[:alnum:] ]") %>% sum()
}
# character vector of length 100K
vec <- rep("Hello. World.", 100000)
# tokenize individual characters for each string
vec_tokens <- purrr::map(vec, function(x) {
stringr::str_split(x, "") %>% unlist()
})
# count non-alphanum characters
purrr::map(vec_tokens, count_non_alnum)
# Time difference of 1.048214 mins
sessionInfo()
# R version 3.4.3 (2017-11-30)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
# Running under: Windows 7 x64 (build 7601) Service Pack 1
我的模拟始终需要大约 1 分钟才能完成。我没有太多期望的基础,但我希望有更快的选择。我愿意接受替代的 R 包或接口(例如 reticulate、Rcpp)。
【问题讨论】:
-
更快:
count_non_alnum2 <- function(x) {sum(grepl("[^[:alnum:] ]", x))}. -
确实快得多。从 1 分钟到 1 秒。将作为答案发布,以便我接受?
-
@RuiBarradas 我试图用 OP 对您的功能进行基准测试,但无法重现效率。我在基准测试中做错了吗
library(microbenchmark); microbenchmark(OP = count_non_alnum(vec), Rui = count_non_alnum2(vec), times = 20L, unit = "relative")# Unit: relative expr min lq mean median uq max neval cld OP 1.00000 1.00000 1.000000 1.000000 1.000000 1.000000 20 a Rui 1.77505 1.76753 1.870186 1.751732 1.715179 3.362217 20 b -
@akrun 您应该在对单个字符进行标记后测试每个函数。
microbenchmark(OP = map(vec_tokens, count_non_alnum), Rui = map(vec_tokens, count_non_alnum2), times = 5L, unit = "relative") -
@DannyMorris 好的,我认为问题出在标记化部分。感谢您的澄清