2

我有一个很长的字符向量(例如“Hello World”等),170 万行,我需要使用两个向量之间的映射替换其中的单词,并将结果保存在同一个向量中。这是一个简单的例子:

library(qdap)
line = c("one", "two one", "four phones")
e = c("one", "two")
r = c("ONE", "TWO")
line = mgsub(e,r,line)

结果:

[1] "ONE"  "TWO ONE" "four phONEs"

如您所见,e[j]in line 的每个实例都被替换为r[j]and only r[j]。它在相对较小的“行”和e->r词汇长度上运行良好,但是当我运行length(line) = 1700000and时length(e) = 750,我达到了分配的总内存:

Reached total allocation of 7851Mb: see help(memory.size)

任何想法如何避免它?

4

3 回答 3

3

stringi包为许多字符串操作提供了快速一致的工具

stri_replace_all_regex(line, paste0("\\b", e, "\\b"), r, vectorize_all = FALSE)

与其他方法一样快(几分之一不同)并且更直接。

于 2015-03-01T18:21:24.820 回答
1

更新问题(对管理员:如果它不值得单独的答案 - 请将其与原始答案合并)。mgsub与简单的for循环相比,运行速度如此之快的原因是默认情况下在mgsub参数fixed = TRUE中,而默认情况下!我刚刚发现它。我想再次澄清一下,这不适合我,因为我不想替换in ,而只想替换整个单词。即我被迫将s 粘贴到模式中。这是我的代码中的三个片段(我测试只是为了查看时差,不打算使用它)。gsubFALSEfixed=TRUEcapscapsulecaps\\bfixed=TRUEgsub

#This is with mgsub. Now with fixed = FALSE!!
i = mgsub(paste("\\b",orig,"\\b",sep=""),change,i,fixed=FALSE)

#This is with a for loop. fixed=TRUE in one of lines is for test purposes only. Do not use
for(k in seq_along(orig)) {
  i = gsub(paste("\\b",orig[k],"\\b",sep=""),change[k],i)
  #i = gsub(orig[k],change[k],i,fixed=TRUE)
}

以下是在不同数量的输入数据上所有三种情况的时间和内存使用情况:

N     | mgsub, fixed=F   | gsub, fixed=F    | gsub, fixed=T
--------------------------------------------------------------
100k  | 41sec, M > 2.3GB | 37sec, M > 0.9GB | 9sec, M > 0.8GB
200k  | 99sec, M > 4GB   | 74sec, M > 1.1GB | 18sec, M > 1.3GB
300k  | 132sec, M > 5.6GB| 112sec, M > 2.6GB| 28sec, M > 1.6GB 
        + disk involved

因此,我得出结论,对于我的应用程序 when fixedmust be FALSE,使用mgsub. 其实forloop更快,不会造成内存溢出!

感谢所有相关人员。我希望我可以给评论者积分,但我不知道如何在“评论”中做到这一点

于 2014-12-09T16:36:19.583 回答
1

我相信你可以使用fixed = TRUE.

您似乎关心听起来像的空格......所以只需在您正在使用的所有 3 个向量的末端添加空格。## Start要运行从到的整个序列## Finish(大约是您的数据大小)需要Time difference of 2.906395 secs170 万个字符串。大部分时间都是在最后剥离多余的空间。

## Recreate data
line <- c("one", "two one", "four phones", "and a capsule", "But here's a caps key")
e <- c("one", "two", "caps")
r <- c("ONE", "TWO", "CAPS")

line <- rep(line, 1700000/length(line))

## Start    
line2 <- paste0(" ", line, " ")
e2 <-  paste0(" ", e, " ")
r2 <- paste0(" ", r, " ")


for (i in seq_along(e2)) {
    line2 <- gsub(e2[i], r2[i], line2, fixed=TRUE)
}

gsub("^\\s|\\s$", "", line2, perl=TRUE)
## Finish

这里qdap没有mgsub用。该软件包专为小得多的数据而设计。此外,这fixed = TRUE是一个明智的默认设置,因为它的速度要快得多。附加软件包的目的是通过重新配置可用工具来改进工作流程(有时是特定于领域/任务的)。该mgsub函数也有一些错误处理和其他细节,这些细节在分析使函数占用内存的转录本时很有用。在安全性+语法糖 速度之间经常存在权衡。

请注意,仅仅因为 2 个函数以相似的方式命名并不意味着任何东西,特别是如果它们在附加包中找到。即使是基本 R 中的函数也有不同的命名和行为默认值(查看apply函数族;这个问题不太理想,但它是 R 历史演变的一部分)。作为用户,您有责任阅读文档而不是做出假设。

于 2014-12-09T23:32:51.413 回答