【问题标题】:Why does gtools::combinations and permutations not work with a vector containing the same elements?为什么 gtools::combinations 和 permutations 不适用于包含相同元素的向量?
【发布时间】:2021-11-10 09:14:29
【问题描述】:

假设我有一个向量vec <- c("H", "H", "H", "H", "M", "M", "A", "A") 如果我例如如何获得所有组合/排列使用预期的输出从 8 个中抽取 5 个。

> head(t, 6)
     [,1] [,2] [,3] [,4] [,5]
[1,] "H"  "H"  "H"  "H"  "M" 
[2,] "H"  "H"  "H"  "H"  "M" 
[3,] "H"  "H"  "H"  "H"  "A" 
[4,] "H"  "H"  "H"  "H"  "A" 
[5,] "H"  "H"  "H"  "M"  "M" 
[6,] "H"  "H"  "H"  "M"  "A" 

我尝试了gtools::combinations(),但我总是收到错误,即不同元素太少(gtools::permutations() 也是如此,无论是否允许重复。 所以我很费力地做到了

t <- gtools::combinations(8, 5, vec, repeats.allowed = F)
Error in gtools::combinations(8, 5, vec, repeats.allowed = F) : 
  too few different elements


t <- gtools::combinations(8, 5, letters[1:8], repeats.allowed = F)

for ( i in 1:8) {
  if ( i <=4 ) {
    t[t == letters[i]] <- "H" 
  } else if (i <= 6) {
    t[t == letters[i]] <- "M" 
  } else if (i <= 8) {
    t[t == letters[i]] <- "A" 
  }
}

我正在从任何包或基础 R 中寻找更简单的解决方案,并想知道为什么它不起作用。提前致谢。

【问题讨论】:

    标签: r combinations permutation


    【解决方案1】:

    另一种选择

    combn(vec,5)
    

    产生 56 种组合 (choose(8,5))。

    【讨论】:

      【解决方案2】:

      当您需要包含重复或multisets 的向量的组合/排列时,基本R 和其他包中的许多可用函数将产生最终需要过滤掉的不必要的重复结果。对于较小的问题,这不是问题,但是这种方法很快就会变得不切实际。

      目前,有几个包能够处理这些类型的问题。他们是arrangementsRcppAlgos(我是作者)。

      vec <- c("H", "H", "H", "H", "M", "M", "A", "A")
      tbl_v <- table(vec)
      
      tbl_v
      vec
      A H M 
      2 4 2 
      
      library(RcppAlgos)
      comboGeneral(names(tbl_v), 5, freqs = tbl_v)
          [,1] [,2] [,3] [,4] [,5]
      [1,] "A"  "A"  "H"  "H"  "H" 
      [2,] "A"  "A"  "H"  "H"  "M" 
      [3,] "A"  "A"  "H"  "M"  "M" 
      [4,] "A"  "H"  "H"  "H"  "H" 
      [5,] "A"  "H"  "H"  "H"  "M" 
      [6,] "A"  "H"  "H"  "M"  "M" 
      [7,] "H"  "H"  "H"  "H"  "M" 
      [8,] "H"  "H"  "H"  "M"  "M"
      
      ## For package arrangements we have:
      ## arrangements::combinations(names(tbl_v), 5, freq = tbl_v)
      

      同样,对于排列,我们有:

      permuteGeneral(names(tbl_v), 5, freqs = tbl_v)
            [,1] [,2] [,3] [,4] [,5]
        [1,] "A"  "A"  "H"  "H"  "H" 
        [2,] "A"  "A"  "H"  "H"  "M" 
        [3,] "A"  "A"  "H"  "M"  "H" 
        [4,] "A"  "A"  "H"  "M"  "M" 
           .   .    .    .    .    .
           .   .    .    .    .    .
           .   .    .    .    .    .
      [137,] "M"  "M"  "H"  "A"  "A" 
      [138,] "M"  "M"  "H"  "A"  "H" 
      [139,] "M"  "M"  "H"  "H"  "A" 
      [140,] "M"  "M"  "H"  "H"  "H" 
      
      ## For package arrangements we have:
      ## arrangements::permutations(names(tbl_v), 5, freq = tbl_v)
      

      这两个包都包含无需过滤即可生成每个结果的算法。这种方法效率更高。

      例如,如果我们有big_vec &lt;- rep(vec, 8),并且我们想要长度为 16 的所有组合。使用过滤方法,需要生成长度为 64 的向量的所有组合,选择 16,然后过滤它们。那是choose(64, 16) = 4.885269e+14 的总组合。这会很困难。

      有了这两个包,这个问题就轻而易举了。

      big_vec <- rep(vec, 8)
      tbl_big_v <- table(big_vec)
      
      tbl_big_v
      big_vec
       A  H  M 
      16 32 16 
      
      system.time(test_big <- comboGeneral(names(tbl_big_v), 16,
                                           freqs = tbl_big_v))
      user  system elapsed 
         0       0       0 
      
      dim(test_big)
      [1] 153  16
      

      【讨论】:

        【解决方案3】:

        apply(gtools::combinations(8,5,repeats.allowed = FALSE),2,\(x) vec[x]) 做你想做的事。 我不知道如果将包应用于向量,为什么包需要不同的值。文档中并不清楚。

        【讨论】:

          猜你喜欢
          • 2017-06-19
          • 1970-01-01
          • 1970-01-01
          • 2016-02-15
          • 1970-01-01
          • 2021-09-17
          • 2020-05-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多