【发布时间】:2016-01-09 08:44:33
【问题描述】:
这里呼吁一种更好的方法来做一些我已经可以低效地做的事情:使用“停用词”过滤一系列 n-gram 标记,以便在n-gram 触发删除。
我非常希望有一种适用于 unigram 和 n-gram 的解决方案,尽管有两个版本是可以的,一个带有“固定”标志,一个带有“正则表达式”标志。我将问题的两个方面放在一起,因为有人可能有一个解决方案,它尝试了一种解决固定和正则表达式停用词模式的不同方法。
格式:
tokens 是字符向量列表,可以是 unigram 或由
_(下划线)字符连接的 n-gram。停用词是一个字符向量。现在我满足于让它成为一个固定的字符串,但是如果能够使用正则表达式格式的停用词来实现它也是一个不错的奖励。
所需输出: 与输入 tokens 匹配的字符列表,但任何与停用词匹配的组件标记都被删除。 (这意味着 unigram 匹配,或匹配 n-gram 所包含的术语之一。)
示例、测试数据、工作代码和基准:
tokens1 <- list(text1 = c("this", "is", "a", "test", "text", "with", "a", "few", "words"),
text2 = c("some", "more", "words", "in", "this", "test", "text"))
tokens2 <- list(text1 = c("this_is", "is_a", "a_test", "test_text", "text_with", "with_a", "a_few", "few_words"),
text2 = c("some_more", "more_words", "words_in", "in_this", "this_text", "text_text"))
tokens3 <- list(text1 = c("this_is_a", "is_a_test", "a_test_text", "test_text_with", "text_with_a", "with_a_few", "a_few_words"),
text2 = c("some_more_words", "more_words_in", "words_in_this", "in_this_text", "this_text_text"))
stopwords <- c("is", "a", "in", "this")
# remove any single token that matches a stopword
removeTokensOP1 <- function(w, stopwords) {
lapply(w, function(x) x[-which(x %in% stopwords)])
}
# remove any word pair where a single word contains a stopword
removeTokensOP2 <- function(w, stopwords) {
matchPattern <- paste0("(^|_)", paste(stopwords, collapse = "(_|$)|(^|_)"), "(_|$)")
lapply(w, function(x) x[-grep(matchPattern, x)])
}
removeTokensOP1(tokens1, stopwords)
## $text1
## [1] "test" "text" "with" "few" "words"
##
## $text2
## [1] "some" "more" "words" "test" "text"
removeTokensOP2(tokens1, stopwords)
## $text1
## [1] "test" "text" "with" "few" "words"
##
## $text2
## [1] "some" "more" "words" "test" "text"
removeTokensOP2(tokens2, stopwords)
## $text1
## [1] "test_text" "text_with" "few_words"
##
## $text2
## [1] "some_more" "more_words" "text_text"
removeTokensOP2(tokens3, stopwords)
## $text1
## [1] "test_text_with"
##
## $text2
## [1] "some_more_words"
# performance benchmarks for answers to build on
require(microbenchmark)
microbenchmark(OP1_1 = removeTokensOP1(tokens1, stopwords),
OP2_1 = removeTokensOP2(tokens1, stopwords),
OP2_2 = removeTokensOP2(tokens2, stopwords),
OP2_3 = removeTokensOP2(tokens3, stopwords),
unit = "relative")
## Unit: relative
## expr min lq mean median uq max neval
## OP1_1 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100
## OP2_1 5.119066 3.812845 3.438076 3.714492 3.547187 2.838351 100
## OP2_2 5.230429 3.903135 3.509935 3.790143 3.631305 2.510629 100
## OP2_3 5.204924 3.884746 3.578178 3.753979 3.553729 8.240244 100
【问题讨论】:
-
tm或qdap中去除停用词的方法不够用?尽管它们以相反的方式工作,但首先删除停用词,然后创建 n-gram。
-
不,这很简单,我正在尝试找出一种在构建后删除包含停用词的 ngram 的有效方法。
-
你在 github 上查看过 Tyler Rinker,termco 的新包吗?这看起来很有希望。还没来得及检查。
-
基本上是
grepl的矢量化版本,用于用c 编写的长向量。是的,我也希望有人会这样写:} @Rcore -
stringi 接近于此,但没有以此处所需的方式进行矢量化。出于这个原因,我没有在示例/基本代码中使用 stringi(尽管它具有许多其他吸引人的属性,但在我的测试中执行此任务的速度并不快)。但也许有人会证明我错了!
标签: r performance n-gram stop-words text-analysis