我想构建一个n-gram'字母文档矩阵',它基本上使用最多n个字母的字母序列而不是典型的字母。以下是我想要实现的简化示例:
> letterDocumentMatrix(c('ea','ab','ca'), c('sea','abs','cab'))
[,sea] [,abs] [,cab]
[ea,] TRUE FALSE FALSE
[ab,] FALSE TRUE TRUE
[ca,] FALSE FALSE TRUE
此类操作是否有名称?是否有任何预先构建的功能来处理这个问题?
最后,我尝试使用grepl,但无济于事:
> outer(c('ea','ab','ca'), c('sea','abs','cab'), grepl)
[,1] [,2] [,3]
[1,] TRUE FALSE FALSE
[2,] TRUE FALSE FALSE
[3,] TRUE FALSE FALSE
Warning message:
In FUN(X, Y, ...) :
argument 'pattern' has length > 1 and only the first element will be used
似乎外部传递grepl的第一个参数,而不是一次传递一个条目,导致grepl只搜索第一个术语,在这种情况下是'a'。
答案 0 :(得分:3)
grepl()
未在其pattern
参数上进行矢量化,这就是您无法从outer()
获得正确结果的原因。以下是使用vapply()
的可能解决方案。
vec <- c("sea", "abs", "cab") ## vector to search
pat <- c("ea", "ab", "ca") ## patterns we are searching for
"rownames<-"(vapply(pat, grepl, NA[seq_along(pat)], vec, fixed = TRUE), vec)
# ea ab ca
# sea TRUE FALSE FALSE
# abs FALSE TRUE FALSE
# cab FALSE TRUE TRUE
这显然会导致您想要的转置版本。为了完全按照您的意愿获得矩阵,我们可以使用lapply()
,rbind()
结果,然后设置名称。
xx <- do.call(rbind, lapply(pat, grepl, x = vec, fixed = TRUE))
dimnames(xx) <- list(pat, vec)
# sea abs cab
# ea TRUE FALSE FALSE
# ab FALSE TRUE TRUE
# ca FALSE FALSE TRUE
我想在t()
结果上使用vapply()
来转置它,但在大型矩阵上它可能会很慢。
答案 1 :(得分:1)
我们可以在Vectorize
outer
获得乐趣
outer(c('ea','ab','ca'), c('sea','abs','cab'), Vectorize(grepl))
# [,1] [,2] [,3]
#[1,] TRUE FALSE FALSE
#[2,] FALSE TRUE TRUE
#[3,] FALSE FALSE TRUE
答案 2 :(得分:0)
有一个预建的功能可以从 quanteda 包中进行文本分析,这将涉及您将字母序列视为&#34;字典:正则表达式和构建文档 - 在每个&#34;文档&#34;中标识这些正则表达式的特征矩阵。通过使用应用的字典整理对dfm()
函数的调用,您将获得确切的返回对象。在这里,我已将其转换为您的问题。
letterDocumentMatrix <- function(txts, pats) {
# create a dictionary in which the key is the same as the entry
pats <- quanteda::dictionary(sapply(pats, list))
# name each "document" which is the text string to be searched
names(txts) <- txts
# interpret dictionary entries as regular expressions
ret <- quanteda::dfm(txts, dictionary = pats, valuetype = "regex", verbose = FALSE)
# transpose the matrix, coerce to dense logical matrix, remove dimnames
ret <- t(as.matrix(ret > 0))
names(dimnames(ret)) <- NULL
ret
}
texts <- c('sea','abs','cab')
patterns <- c('ea','ab','ca')
letterDocumentMatrix(texts, patterns)
## sea abs cab
## ea TRUE FALSE FALSE
## ab FALSE TRUE TRUE
## ca FALSE FALSE TRUE
如果你想让它在大型数据集上快速工作,我建议从函数中删除第三行和倒数第二行。