R:获取字符串中每个单词排列的内存有效方法

时间:2019-04-03 19:07:08

标签: r nlp out-of-memory permutation

我有一个带有单词列表的字符串,我想从中获取所有可能的单词组合。

fruits <- "Apple Banana Cherry"

要获得此输出:

"Apple, Banana, Cherry, Apple Banana, Apple Cherry, Banana Cherry, Apple Banana Cherry"

使用定义的功能here,对其进行了稍微的修改:

f1 <- function(str1){
  v1 <- strsplit(str1, ' ')[[1]]
  paste(unlist(sapply(seq(length(v1)), function(i)
    apply(combn(v1, i), 2, paste, collapse=" "))), collapse= ', ')
}

f1(fruits)

当行数相对较少时,这很好用,但实际示例中3,350行中共有93,300个字符,中位字符串长度为25个字符,从而导致类似于this:的错误

  

粘贴错误(unlist(sapply(seq(length(v1)),function(i)apply(combn(v1,:     结果将超过2 ^ 31-1个字节

我尝试在函数中将utils::combn更改为RcppAlgos::comboGeneral,因为它显然是quicker,但仍然遇到相同的问题。有什么解决方法的建议吗?

3 个答案:

答案 0 :(得分:2)

我们为 quanteda 中的向量化跳过图和ngram提供了相当有效的功能。尝试使用多线程来提高效率(您可以将线程更改为系统的最大数量):

library("quanteda")
## Package version: 1.4.3
## Parallel computing: 2 of 12 threads used.
## See https://quanteda.io for tutorials and examples.
## 
## Attaching package: 'quanteda'
## The following object is masked from 'package:utils':
## 
##     View
quanteda_options(threads = 4)

fruits <- "Apple Banana Cherry"
tokens(fruits) %>%
  tokens_skipgrams(., n = seq_len(ntoken(.)), skip = 0:ntoken(.), concatenator = " ") %>%
  as.character() %>%
  paste(collapse = ", ")
## [1] "Apple, Banana, Cherry, Apple Banana, Apple Cherry, Banana Cherry, Apple Banana Cherry"

答案 1 :(得分:2)

如果您有三个字

fruits <- "Apple Banana Cherry"
可以通过使用0或1表示每个单词的包含来表示组合。 这意味着使用三个单词,您将拥有2 ^ 3-1-1 = 7个选项,不包括null:

001 Cherry
010 Banana
011 Banana, Cherry
100 Apple
101 Apple, Cherry
110 Apple, Banana
111 Apple, Banana, Cherry

因此,我们可以将其视为二进制计数。所有三个单词的组合都可以用三个位表示,并且有2 ^ 3-1-1 = 7个选项。

存储每个组合的问题是此列表的长度每增加一个单词就会加倍。到您有80个单词时,将需要80位来表示每个可能的组合,但是将有2 ^ 80-1 =大约1,200,000,000,000,000,000,000,000(1.2E24)个不同的可能组合,这将比其中的所有硬盘驱动器占用更多空间世界。

我并不是要暗示这是一个无法解决的问题,也不是我的经验领域来判断其他答案是否可以有效地满足您的需求,但我只是想观察一下会有物理上的限制使得按照问题提出的方式预先计算和存储所有可能的组合是不切实际的。

答案 2 :(得分:1)

为了使问题变得简单,我省略了我最终想要做的就是创建这些组合的列表。

我也不知道它的名字是 tokenisation Skip-Gram 。尽管最终仍然很慢,但该解决方案避免了R内存错误,并具有足够的计算能力,可以解决此问题:

library(tokenizers)
unlist(tokenize_skip_ngrams(fruits, n = 3, n_min = 1, k = 3))