【问题标题】:Faster alternative methods to for-loop in R for pattern matching用于模式匹配的 R 中 for 循环的更快替代方法
【发布时间】:2013-07-17 08:27:32
【问题描述】:

我正在解决一个问题,其中我必须有两个数据框数据和缩写,我想将数据中存在的所有缩写替换为它们各自的完整形式。到目前为止,我一直在以下列方式使用for-loops

abb <- c()
for(i in 1:length(data$text)){
  for(j in 1:length(AbbreviationList$Abb)){
    abb <- paste("(\\b", AbbreviationList$Abb[j], "\\b)", sep="")
    data$text[i] <- gsub(abb, AbbreviationList$Fullform[j], tolower(data$text[i]))
  }
}

缩写数据框如下图所示,可以使用以下代码生成

Abbreviation <- c(c("hru", "how are you"), 
                  c("asap", "as soon as possible"), 
                  c("bf", "boyfriend"), 
                  c("ur", "your"), 
                  c("u", "you"),
                  c("afk", "away from keyboard"))
Abbreviation <- data.frame(matrix(Abbreviation, ncol=2, byrow=T), row.names=NULL)

名称(缩写)

并且数据只是一个数据框,其中 1 列在每行中都有文本字符串,也可以使用以下代码生成。

data <- data.frame(unlist(c("its good to see you, hru doing?", 
                            "I am near bridge come ASAP",
                            "Can u tell me the method u used for",
                            "afk so couldn't respond to ur mails",
                            "asmof I dont know who is your bf?")))
names(data) <- "text"

最初,我有大约 1000 个观察值和大约 100 个缩写的数据框。因此,我能够运行分析。但是现在数据已经增加到将近 50000 个,我在处理它时遇到了困难,因为有两个 for-loops 这使得处理过程非常缓慢。你能推荐一些更好的替代for-loop 并举例说明如何在这种情况下使用它。如果这个问题可以通过矢量化方法更快地解决,那么请建议如何做到这一点。

感谢您的帮助!

【问题讨论】:

  • “示例”是指我可以剪切并粘贴到我的 R 以检查我的答案的内容,而不是我必须手动重新输入的屏幕截图 :-)
  • dput(head(AbbreviationList)) 为例
  • @January 请检查更新后的描述
  • @Ankit 好的,我在答案中发现了一个错误,但现在它可以工作了。请注意,在您的原始脚本中测试时,您有“AbbreviationList”和“Abb”,但在示例中您使用了“Abbreviation”和“abb”(我也使用了后一种形式)。
  • @January 很抱歉,因为我只为你们创建了数据生成代码,所以出现了一些拼写错误......

标签: r plyr apply


【解决方案1】:

这应该更快,而且没有副作用。

mapply(function(x,y){
  abb <- paste0("(\\b", x, "\\b)")
  gsub(abb, y, tolower(data$text))
},abriv$Abb,abriv$Fullform)
  1. gsub 是矢量化的,所以不给它一个字符向量来寻找匹配项。这里我给它data$text
  2. 我使用mapply来避免for的副作用。

【讨论】:

  • 这看起来不错,但它创建了一个nrows(data) x nrows(Abbreviations) 的矩阵。但是有什么办法可以将其转换为nrow(data) x 1 矩阵
  • @Ankit 您应该创建一个具有所需输出的可重现示例。
  • 实际上,正如我所提到的,我想用它们的完整形式替换缩写词。所以,我想得到与输入数据具有相同维度的输出。
【解决方案2】:

首先,显然没有必要在循环的每次迭代中编译正则表达式。此外,实际上不需要循环遍历data$text:在 R 中,您通常可以使用值可以执行的向量——R 将遍历向量的所有元素并返回相同长度的向量.

Abbreviation$regex <- sprintf( "(\\b%s\\b)", Abbreviation$abb )

for( j in 1:length( Abbreviation$abb ) ) {
    data$text <- gsub( Abbreviation$regex[j], 
                       Abbreviation$Fullform[j], data$text,
                       ignore.case= T )
 }

以上代码适用于示例数据。

【讨论】:

  • 这肯定会减少一个 for 循环。是否可以用apply函数替换另一个?
  • 我已经尝试了以下代码,但它没有给出预期的结果,任何错误可能出在哪里的想法。 lapply(Abbreviation$abb, function(x){data$text
  • 简单地说:在函数闭包内 (function(x){ ... }) 你不能修改 data。使用 for 循环,在这种情况下它不会比 lapply 慢。
猜你喜欢
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多