【发布时间】:2018-02-19 02:41:00
【问题描述】:
我有一个包含 2M 观察的数据集。我需要搜索最多 50 个字符列来计算(然后过滤)哪些观察以最多 20 个字符串中的任何一个开头。
我编写了代码,它返回每个字符串被找到的频率;但它太慢了。在 100k 观察(9 列,33 个搜索字符串)上运行此程序需要 2 分钟,并且似乎是线性扩展的(对于完整数据集意味着 ≈30 分钟)。我可以在几秒钟内完成 SAS,并且在配备 SSD 的快速笔记本电脑上运行,所以我假设我的代码是问题所在(不是机器或问题本身)。
set.seed(42)
df_to_search <- cbind.data.frame(
"a"=replicate(1e5,paste0(sample(c(LETTERS,1:10),5,replace = T),collapse = "")),
"b"=replicate(1e5,paste0(sample(c(LETTERS,1:10),5,replace = T),collapse = "")),
"c"=replicate(1e5,paste0(sample(c(LETTERS,1:10),5,replace = T),collapse = "")),
"d"=replicate(1e5,paste0(sample(c(LETTERS,1:10),5,replace = T),collapse = "")),
"e"=replicate(1e5,paste0(sample(c(LETTERS,1:10),5,replace = T),collapse = "")))
search_strings <- c("AB","BC","CD","DE","EF","G6","F8","H1","I9","J7") %>% paste0("^",.) %>% as.vector()
sapply(search_strings, function(y)
apply(df_to_search, 1, function(x) {
str_detect(x, y)
})) %>% colSums()
此代码产生以下结果:
^AB ^BC ^CD ^DE ^EF ^G6 ^F8 ^H1 ^I9 ^J7
394 392 387 389 359 417 397 780 378 382
注意:我将搜索字符串转换为向量,以便将其传递给apply,这将速度提高了 3 倍(与嵌套的 sapply 相比)。我尝试过嵌套的 apply 语句,但它没有导致加速。我还将^ 作为正则表达式语法的一部分添加到搜索字符串之前,以将搜索限制为字符串的开头。我对完全不同的方法持开放态度,但我必须能够使用多个字符串、多列搜索字符串的开头,并返回每个搜索字符串的计数。
编辑/更新 这些解决方案比我的要快得多。谢谢!不幸的是,我的示例搜索字符串(无意中)具有误导性。道歉。我的实际搜索字符串的长度不同,有时是所有数字,从 2 到 5 个字符不等。我应该使用类似的东西:
search_strings <- c("64651","BC","654","DEF","EF","G6","F8","25","I9","J7")
我想不出一种获得最快代码的方法:table(substr(unlist...)) 可以轻松处理不同的搜索字符串长度,但 colSums(vapply(...{vapply...})) 工作得很好。
当然欢迎任何有关此新信息的建议,但否则我认为这是可以回答的。再次感谢。
【问题讨论】: