需要加速从文本列表创建bigram的函数

需要加速从文本列表创建bigram的函数,r,nlp,R,Nlp,我有一个单词列表,如下所示: [[1]] [1] 棕色狐狸跳得很快 [[2]] [1] 曾经的午夜沉闷 [[3]] [1] 乌鸦永不复返 我想做的是根据这个列表创建一组比例尺大得多的比例尺。下面是我的代码,它可以工作。问题是它太慢了。我知道我在bigram_列表中的循环正在减慢速度,但我不知道如何将Lappy与列表一起使用。我还怀疑数据表和rbindlist会有很大帮助,但我似乎也无法让它们发挥作用。任何帮助都会受到哈利路亚合唱团的欢迎 bigram_list <- function(wo

我有一个单词列表,如下所示:

[[1]] [1] 棕色狐狸跳得很快

[[2]] [1] 曾经的午夜沉闷

[[3]] [1] 乌鸦永不复返

我想做的是根据这个列表创建一组比例尺大得多的比例尺。下面是我的代码,它可以工作。问题是它太慢了。我知道我在bigram_列表中的循环正在减慢速度,但我不知道如何将Lappy与列表一起使用。我还怀疑数据表和rbindlist会有很大帮助,但我似乎也无法让它们发挥作用。任何帮助都会受到哈利路亚合唱团的欢迎

bigram_list <- function(words, ng) {
    tokens <- character()

    words_length <- length(words)
    for (i in 1:words_length) {
        set <- words[[i]]          ##current vector of words
        end <- length(set)
        if (end > 2) {
            if (ng == 1) {
                nlist <- set[1:(end-1)]
            } else {
                nlist <- set[2:end]
            }
            tokens <- c(tokens,nlist) 
        }
    }
    return(tokens)
}

make_bigram <- function(words) {
    n1s <- character()
    n2s <- character()

    n1.set <- bigram_list(words, 1)
    n1s <- c(n1s, n1.set)

    n2.set <- bigram_list(words, 2)
    n2s <- c(n2s, n2.set)

    bigrams <- data.frame(n1=n1s, n2=n2s)
    return(bigrams)
}

我在Python中执行此操作的方式是:

zip(tokens[:-1],tokens[1:])
这里有两件事:列表切片和压缩

使用列表切片可以剪切列表的各个部分。在本例中,我们实际上分别从列表中删除最后一个和第一个标记,但仅选择切片中除最后一个标记外的所有标记和除第一个标记外的所有标记

zip组合了两个列表,其中每个列表中的并行条目形成一个元组;R中的mapply似乎与我们的目的非常相似

在R中,这似乎有效:

> tokens <- list("I", "am", "a", "banana",".")
> mapply(list,tokens[1:length(tokens)-1], tokens[2:length(tokens)])
     [,1] [,2] [,3]     [,4]    
[1,] "I"  "am" "a"      "banana"
[2,] "am" "a"  "banana" "."     

要仅获取bigram,可以使用ngram包。它非常快,因为它是用C编写的。然而,当前版本似乎只允许导出n-gram,而不允许导出它们各自的频率

为了获得频率,你可以使用tau软件包。textcnt可以返回n-gram及其频率

在下面的基准测试中,我们可以看到ngram比textcnt快得多,但这里的比较并不完全公平,因为textcnt也计算频率

text <- list("This is just an example for Stackoverflow",
             "The quick brown fox jumps over the lazy dog",
             "And another example sentence to test the function",
             "This is the end of the list")
# Repeat to make the list larger
text <- rep(text, 1000)

### Using the tau package --------------------------------
library(tau)
# Find and count n-grams. Treats list elements separately.
# (For example there is no bigram "stackoverflow the")
ngrams <- textcnt(text, method = "string", n = 2L, decreasing = T)
# > head(ngrams, 3)
# this is      an example     and another
# 2000            1000            1000

## Apply over separate list elements
ngrams <- lapply(text, 
                 function(x) textcnt(x, 
                                     method = "string", 
                                     n = 2L, 
                                     decreasing = T))

### Using the ngram package -------------------------------
# This works only on a string, not a list. 
# Does not return frequencies
library(ngram)
ngram <- ngram(paste(unlist(text), collapse = " "), 
               n = 2L)
ngram <- get.ngrams(ngram)
# > head(ngram, 3)
# [1] "just an"     "The quick"   "is the" 

### Benchmarks ---------------------------------------------
library(microbenchmark)
microbenchmark(ngram(paste(unlist(text), collapse = " "), 
                              n = 2L))
# mean 34.3, median 33.7
microbenchmark(textcnt(text, method = "string", n = 2L, decreasing = T))
# mean 223.7, median 220.6 

你只需要这些大字还是那些大字的计数?我需要实际的大字。一旦我把它们放在一个数据帧中,我就可以使用一个数据表来稍微快速地聚合它们。我的最终目标是建立一组Bigram和它们的频率。这是一个有趣的想法,但我如何才能让它对整个列表起作用呢?我的短测试集是:l1你的单子是单独的文档还是句子?你可能不想在句子之间形成复句。没有理由在文档之间形成bigram。至于遍历各个列表,请使用for循环。