R:以P的倍数生成N个权重的所有排列

时间:2011-07-31 18:50:11

标签: r permutation combinations combinatorics

我需要创建一个函数(在R中),其中:
- 给予 N 可能的变量以将权重归因于;
- 创建所有可能的权重(总和为100%);
- 受限于权重必须以 P 的倍数出现(通常为1%)

显然,由于N和P是反向相关的 - 即我不能指定 N = 7,并且 P = 0.4。但是,我希望只能指定整数解,即 P = 0.01。

很抱歉,如果这是一个众所周知的问题 - 我不是数学家,我使用我认识的术语进行了搜索,但没有发现任何足够接近的内容。

我发布了我写过的代码,但是......它并不令人印象深刻或富有洞察力。

感谢您的帮助!

2 个答案:

答案 0 :(得分:5)

假设权重的顺序很重要,这些是组合;如果他们不这样做那么分区。在任何一种情况下,它们都受到部件数量的限制,即你所谓的N,尽管后面的代码使用numparts。还存在是否允许权重为0的问题。

由于您希望权重加起来为1,因此您需要1 / p为整数,在以下代码中为sumparts;它不取决于重量的数量。获得合成后,您可以将它们乘以p,即除以n,以获得权重。

R具有partitions包以生成此类组合或受限制的分区。以下代码应该是自解释的:矩阵中的每一列都是一组权重。我有七个权重,p = 0.1或10%,禁止权重为0:这提供了84种可能性;允许权重为0意味着8008种可能性。当p = 0.01或1%时,将有1,120,529,256种可能性,其中权重为0,而1,705,904,746为。如果订单无关紧要,请使用restrictedparts代替compositions

> library(partitions)
> numparts <- 7  # number of weights
> sumparts <- 10  # reciprocal of p
> weights <- compositions(n=sumparts, m=numparts, include.zero=FALSE)/sumparts
> weights

[1,] 0.4 0.3 0.2 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1
[2,] 0.1 0.2 0.3 0.4 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1
[3,] 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.1 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2
[4,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

[1,] 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.3 0.2 0.1
[2,] 0.1 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.3
[3,] 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[4,] 0.4 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[5,] 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.3 0.4 0.1 0.1 0.1
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

[1,] 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.3
[2,] 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[3,] 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[4,] 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[6,] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.3 0.3 0.4 0.1
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2

[1,] 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[2,] 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[3,] 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[4,] 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.1 0.2
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2
[7,] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2

[1,] 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1
[2,] 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[3,] 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[4,] 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[6,] 0.3 0.1 0.1 0.1 0.1 0.1 0.2 0.1
[7,] 0.2 0.3 0.3 0.3 0.3 0.3 0.3 0.4

答案 1 :(得分:2)

编辑:功能已更新,因为它提供了两次结果。

您可以根据递归计算尝试此功能。无论订单如何,它都会为您提供所有可能的组合。我已经这样做了,因为否则会获得具有所有可能排列的多个行。

计算基于整数。最小权重P设定为1,Pint成为可分割的权重单位数。 max.W将是可以赋予​​一个变量的最大单位数量。

算法如下:

  • 如果N = 2,则根据给定的最小和最大权重进行所有可能的组合。

  • 如果N> 2,将此算法应用于N = 1到天花板(最大重量/ N),最大重量指定为当前最大重量+1减去N,最小重量指定为N.

这为您提供了所有可能的整数组合。乘以P得出原始权重。

或在功能中:

myfunc <- function(N,P){
  if(100%%(P*100) !=0){
    stop("100% cannot be divided in portions of P")
  }
  Pint <- 100/(P*100)
  max.W <- Pint- N + 1

  combs <- function(n,max.w,min){
    mw <- max.w + 1

    if(n==2){

      w <- seq.int(min,floor((mw)/2))
      out <- cbind(w,mw-w)

    } else if (n > 2){

      x <- lapply(1:ceiling(max.w/n),function(i){

        newcombs <- combs(n-1,mw-i,i)
        cbind(newcombs,rep(i,nrow(newcombs)))

      })

      out <- do.call("rbind",x)
    }
    colnames(out) <-rownames(out) <- NULL
    out
  }  
  res <- combs(N,max.W)
  apply(res,1,sort)*P
}

这给出了矩阵列中的组合:

> Y <- myfunc(3,0.1)
> Y
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]  0.1  0.1  0.1  0.1  0.2  0.2  0.2  0.3
[2,]  0.1  0.2  0.3  0.4  0.2  0.3  0.4  0.3
[3,]  0.8  0.7  0.6  0.5  0.6  0.5  0.4  0.4

警告!使用你提供的测试用例(7个变量,跳跃0.01),你将计算很长时间的大量可能性。当N = 7且P = 0.04时,您已经有3555种可能的组合。当N = 0.2时,变为336,443种可能性。如果这就是你所追求的,你必须考虑到这些组合的每一种可能的排列。