【问题标题】:Fast string matching in RR中的快速字符串匹配
【发布时间】:2015-05-06 01:04:34
【问题描述】:

我正在尝试在大型数据集中进行单词匹配。我想知道是否有一种方法可以加快我的工作流程中最慢的操作。

我的目标是在单词词典和单词向量列表之间找到匹配的位置。

words <- c("cat", "dog", "snake", "cow")
scores <- c(1.5, 0.7, 3.5, 4.6)
dic <- data.frame(words, scores)

wordList <- list(c("jiraffe", "dog"), c("cat", "elephant"), c("snake", "cow"))

到目前为止,我发现最快的方法是这样做:

matches <- function(wordList) {
    subD <- which(dic$words %in% wordList)
}

我想要的输出是:

matches(wordList):
list(c(2), c(1), c(3, 4))

我以后可以用它来获得每个 wordList 单元格的平均分数

averageScore <- sapply(matches, function(x) {mean(dic[x, "scores"]})

有没有比我在函数中做的更快的字符串匹配方法:

subD <- which(dic$words %in% wordList)

我尝试了 dplyr 方式,认为它可能会更快,使用第一个“过滤器”获取“dic”的子集并在其上应用“colMeans”,但它似乎慢了一倍。

此外,在循环中运行我的匹配函数与在其上使用“lapply”一样慢。

我错过了什么吗?有没有比两者都快的方法?

【问题讨论】:

  • 有快速匹配的包,如fastmatch;和data.table 包中的chmatch 函数。可能,这些比我们可以在几行基础 R 中得到的任何东西都好。
  • 是否绝对要求您使用要匹配的词向量列表的数据结构?您的减速将出现在调用 sapply() 时使用的 for 循环结构中。我会通过构造一个长格式数据结构来向量化这个操作,然后你可以用 dplyr 或类似的东西轻松地总结它。如果你愿意,我可以用这种结构起草一个答案。
  • 要扩展Forrest的评论,可以从一个列表开始(方便输入组,然后转换为mydf &lt;- data.frame(w=unlist(wordList),g=rep(1:length(wordList),sapply(wordList,length)))以便更快地分析。
  • 或者,ww &lt;- setNames(wordList,1:length(wordList)); stack(ww)。最好只为列表中的组分配合理的名称,在这种情况下,不需要第一步。
  • 如果您的数据实际上很大(不适合 RAM),那么无论如何您都不应该使用 R。如果你要匹配很多次,那么你应该使用 btree。

标签: r string


【解决方案1】:

这是一种选择:

library(data.table)
nn <- lengths(wordList)  ## Or, for < R-3.2.0, `nn <- sapply(wordList, length)` 
dt <- data.table(grp=rep(seq_along(nn), times=nn), X = unlist(wordList), key="grp")
dt[,Score:=scores[chmatch(X,words)]]
dt[!is.na(Score), list(avgScore=mean(Score)), by="grp"]
#    grp avgScore
# 1:   1     0.70
# 2:   2     1.50
# 3:   3     4.05

【讨论】:

  • 谢谢乔希,这个解决方案很优雅,比我的解决方案快得多!
猜你喜欢
  • 2014-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
相关资源
最近更新 更多