使用 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