【问题标题】:R Combinatoric Sequence GenerationR组合序列生成
【发布时间】:2020-11-04 08:52:37
【问题描述】:

我正在尝试生成一个矩阵,其中每列代表 R 中的一系列因子。这些因子可以采用值 1、2、3 或 4。每个序列有 13 个元素,表明总共有 4^13 个潜在序列。然而,只有这些潜在序列的特定子集被认为是有效的。逻辑如下:

  1. 序列可以从任何因子开始
  2. 如果一个序列从 4 开始,它的第二个元素可以小于或等于 4
  3. 一旦元素下降到 4 以下,后续条目必须微弱增加
  4. 如果一个序列以 1、2 或 3 开头,它一定是微弱递增的

例如,序列 (1,2,3,3,3.....3) 是有效的。序列 (4,4,1,1,2,4,4....4) 也是有效的。序列 (4,1,2,3,1,1....1) 不是,因为它在第一次从 4 下降到 1 后并没有弱增加。

目前,我有代码来组合 2&3 因子并生成这个矩阵。该过程涉及生成所有可能序列的矩阵,然后根据上述逻辑进行过滤。这是非常低效的,但如果有必要我可以发布它。这个过程也不能推广到四因素模型,因为 4^13 个潜在序列使我的机器不堪重负。

如果你们中的任何人能提供有关我如何生成这些有效序列的见解,我们将不胜感激。谢谢。

【问题讨论】:

    标签: r math


    【解决方案1】:

    我假设一旦逐渐增加的向量达到 4,它就不能像 4 是第一个数字那样再次跳回较低的值(如果可以,代码实际上更容易)。

    以下函数生成兼容序列,本质上是使用switch来实现马尔可夫链

    generate_seq <- function(n)
    {
      x    <- numeric(n)
      x[1] <- sample(4, 1)
      had_a_four <- FALSE
      
      for(i in seq(n - 1)) {
        if(!had_a_four)
        {
          x[i + 1]  <- switch(x[i], sample(1:2, 1, prob = c(3, 1)), 
                                    sample(2:3, 1, prob = c(3, 1)), 
                                    sample(3:4, 1, prob = c(3, 1)), 
                                    sample(4, 1))
        }
        else
        {
          x[i + 1]  <- switch(x[i], sample(1:2, 1, prob = c(3, 1)), 
                                    sample(2:3, 1, prob = c(3, 1)), 
                                    sample(3:4, 1, prob = c(3, 1)),  
                                    4)
        }
       if(x[i + 1] == 4 & !all(x[1:(i+1)] == 4)) had_a_four <- TRUE
      }
      x
    }
    

    我们可以像这样生成一个 4 列矩阵:

    set.seed(4)
    matrix(replicate(4, generate_seq(13)), ncol = 4)
    #>       [,1] [,2] [,3] [,4]
    #>  [1,]    4    4    1    1
    #>  [2,]    3    3    1    2
    #>  [3,]    3    4    2    3
    #>  [4,]    3    4    2    3
    #>  [5,]    4    4    2    4
    #>  [6,]    4    4    3    4
    #>  [7,]    4    4    3    4
    #>  [8,]    4    4    3    4
    #>  [9,]    4    4    4    4
    #> [10,]    4    4    4    4
    #> [11,]    4    4    4    4
    #> [12,]    4    4    4    4
    #> [13,]    4    4    4    4
    

    【讨论】:

    • 这是优秀的艾伦,谢谢!我可以生成大量列,然后删除重复项以获得详尽的序列集合。我可以将其保存为 .csv,并在需要时调用该文件。
    • 我认为这是不正确的,因为它没有考虑到如果第二个元素是 4,序列可以在第二个元素之后下降(即 OP 声明 (4,4,1,1,2,4,4....4) 是有效的序列)。
    • 没错,只要所有先行元素都是4s,一个序列就可以丢弃一次。因此,例如,如果一个序列的前 5 个元素都是 4,那么第六个元素可能是 1、2、3 或 4。一旦一个序列从 4 下降,其余元素肯定会微弱增加。
    • @27ϕ9 Thanjs - 我想我错过了。但是,这不会使函数产生的任何序列出错;它只是意味着它错过了一小部分样本空间。将 if(x[i + 1] == 4) 更改为 if(x[i + 1] == 4 &amp; !all(x == 4)) 可以解决此问题。
    • 是的,抱歉,并不是暗示生成的序列是错误的,只是它不能用于生成 OP 似乎想要的详尽列表。
    【解决方案2】:

    我认为您可以使用RcppAlgos 通过生成长度为 1:n 的向量的组合来有效地做到这一点(假设较短的向量用4 填充到长度为 13):

    library(RcppAlgos)
    
    get_combos <- function(n) {
      unique(do.call(rbind, sapply(rev(seq(n)), function(x)
        do.call(
          cbind, c(rep(4, n - x), list(comboGeneral(1:4, x, TRUE)))
        ))))
    }
    
    res <- get_combos(13)
    
    head(res)
    
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
    [1,]    1    1    1    1    1    1    1    1    1     1     1     1     1
    [2,]    1    1    1    1    1    1    1    1    1     1     1     1     2
    [3,]    1    1    1    1    1    1    1    1    1     1     1     1     3
    [4,]    1    1    1    1    1    1    1    1    1     1     1     1     4
    [5,]    1    1    1    1    1    1    1    1    1     1     1     2     2
    [6,]    1    1    1    1    1    1    1    1    1     1     1     2     3
    
    nrow(res)
    [1] 2367
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-19
      • 2013-09-16
      • 2019-11-02
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多