使用 R 获取总和为 100 的所有组合

Posted

技术标签:

【中文标题】使用 R 获取总和为 100 的所有组合【英文标题】:Getting all combinations which sum up to 100 using R 【发布时间】:2014-04-08 17:51:12 【问题描述】:

我需要使用 8 个变量来获取总和等于 100 的所有组合,这些变量可以通过 10 的增量步长取 0 到 100 之间的任何值。(即 0、10、20 ... 100)

下面的脚本就是这样做的,但是效率很低,因为它创建了一个巨大的数据集,我想知道是否有人有更好的方法来做到这一点。

x <- expand.grid("ON" = seq (0,100,10), 
        "3M" = seq(0,100,10), 
        "6M" = seq(0,100,10), 
        "1Y" = seq(0,100,10), 
        "2Y" = seq(0,100,10),
        "5Y" = seq(0,100,10), 
        "10Y" = seq(0,100,10), 
        "15Y" = seq(0,100,10))

x <- x[rowSums(x)==100,]

编辑 --

回答 Stéphane Laurent 的问题

结果应该是这样的

ON 3M 6M 1Y 2Y 5Y 10Y 15Y        
100 0  0  0  0  0   0   0  
 90 10  0  0  0  0   0   0  
 80 20  0  0  0  0   0   0  
 70 30  0  0  0  0   0   0  
 60 40  0  0  0  0   0   0  
 50 50  0  0  0  0   0   0

(...)

  0 0  0  0  0  0 10  90  
  0 0  0  0  0  0  0 100

【问题讨论】:

rosettacode.org/wiki/Count_the_coins @Josh O'Brien 的“非expand.grid”答案here 是否相关? 【参考方案1】:

按照 Stéphane Laurent 的回答,我可以通过使用 uniqueperm2 函数 here 获得超快速的解决方案。

library(partitions)

C = t(restrictedparts(10,8))
do.call(rbind, lapply(1:nrow(C),function(i)uniqueperm2(C[i,])))

更新,使用iterpc包有更快的解决方案。

library(partitions)
library(iterpc)
C = t(restrictedparts(10,8))
do.call(rbind, lapply(1:nrow(C),function(i) getall(iterpc(table(C[i,]), order=T))))

速度大约是uniqueperm2的两倍

> f <- function()
    do.call(rbind, lapply(1:nrow(C),function(i)uniqueperm2(C[i,])))

> g <- function()
    do.call(rbind, lapply(1:nrow(C),function(i) getall(iterpc(table(C[i,]), order=T))))

> microbenchmark(f(),g())
Unit: milliseconds
 expr      min       lq     mean   median       uq      max neval cld
  f() 36.37215 38.04941 40.43063 40.07220 42.29389 46.92574   100   b
  g() 16.77462 17.45665 19.46206 18.10101 20.65524 64.11858   100  a 

【讨论】:

【参考方案2】:

这是你想要的吗:

> library(partitions)
> 10*restrictedparts(10,8)

[1,] 100 90 80 70 60 50 80 70 60 50 60 50 40 40 70 60 50 40 50 40 30 40 30 60 50 40 40 30 30 20 50 40 30 30 20 40 30 20 30 20
[2,]   0 10 20 30 40 50 10 20 30 40 20 30 40 30 10 20 30 40 20 30 30 20 30 10 20 30 20 30 20 20 10 20 30 20 20 10 20 20 10 20
[3,]   0  0  0  0  0  0 10 10 10 10 20 20 20 30 10 10 10 10 20 20 30 20 20 10 10 10 20 20 20 20 10 10 10 20 20 10 10 20 10 10
[4,]   0  0  0  0  0  0  0  0  0  0  0  0  0  0 10 10 10 10 10 10 10 20 20 10 10 10 10 10 20 20 10 10 10 10 20 10 10 10 10 10
[5,]   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 10 10 10 10 10 10 20 10 10 10 10 10 10 10 10 10 10
[6,]   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 10 10 10 10 10 10 10 10 10 10
[7,]   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 10 10 10 10 10
[8,]   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 10 10

【讨论】:

不完全是,请参阅原始问题中的编辑 @user3387134 好吧,如果你有这个结果,应该很容易创建所有排列。 嘿@Stephane,我不确定这是否在 2014 年可用,但在与 partitions 相同的包中有一个名为 compositions 的函数,它返回所有可能的编写方法整数 (en.wikipedia.org/wiki/Composition_(combinatorics))。因此,在我的机器上调用 compositions(10, 8) 会在大约 2 毫秒内返回所有 19448 个结果(OP 正在寻找的结果)。【参考方案3】:

partitions 包包含函数 compositions(),它完全符合 OP 的要求。

library(partitions)

# Get 8 elements that sum up to 10
x <- compositions(n = 10, m = 8, include.zero = T)

# Convert partition to matrix
x <- as.matrix.partition(x)

# Transpose matrix
x <- t(x)

# Multiply by 10 so that elements take any value from 0 to 100 by incremental step of 10
x <- x * 10

head(x)
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,]  100    0    0    0    0    0    0    0
#> [2,]   90   10    0    0    0    0    0    0
#> [3,]   80   20    0    0    0    0    0    0
#> [4,]   70   30    0    0    0    0    0    0
#> [5,]   60   40    0    0    0    0    0    0
#> [6,]   50   50    0    0    0    0    0    0

tail(x)
#>          [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [19443,]    0    0   10    0    0    0    0   90
#> [19444,]    0    0    0   10    0    0    0   90
#> [19445,]    0    0    0    0   10    0    0   90
#> [19446,]    0    0    0    0    0   10    0   90
#> [19447,]    0    0    0    0    0    0   10   90
#> [19448,]    0    0    0    0    0    0    0  100

另见@Joseph Woods Finding A List of All Combinations of 6 Numbers That Add up to 10的回答

【讨论】:

以上是关于使用 R 获取总和为 100 的所有组合的主要内容,如果未能解决你的问题,请参考以下文章

Linq查询以获取最多为N的所有数字(正数和负数),总和为数字K

Python:获取列表顺序元素的所有组合

r语言如何求矩阵中某一列的总和

#yyds干货盘点# LeetCode 热题 HOT 100:组合总和

获取R中的所有组合,允许重复

获取JAVA中的数字总和