R中expand.grid函数的修改

4
我需要创建一个所有可能组合的矩阵。
L<-12 
vec <- c(0:21)
lst <- lapply(numeric(L), function(x) vec)
Mat1<-as.matrix(expand.grid(lst))

结果将是非常大的矩阵,我的计算机无法计算。实际上,我只需要第一列中的值大于第二列中的值,第二列中的值大于第三列中的值等等的组合。我能否以某种方式修改expand.grid函数以删除不必要的组合?


向量0:21是您感兴趣的数字,还是只是为了让我们有东西可以处理而创建的示例向量?如果是前者,那么下面基于组合的答案将起作用;否则,它们将无法起作用... - Spacedman
@Spacedman,如果我没记错的话,更健壮的版本将处理(1)重复项和(2)缺失值。我认为OP的主要问题是创建一个22^12大小(380 petabit)的大量输出(不可能),并对其进行子集化以满足他的需求 - 下面的两个答案都解决了这个问题,并且如果我没记错的话,可以通过进一步的子集来适应这些概括。 - MichaelChirico
如果组成向量甚至没有排序怎么办?这就是为什么我喜欢在这种情况下询问澄清问题之后再发布答案!我想OP可能是指“组合”,这可能意味着combn(0:21,11)(或类似的东西)... - Spacedman
2个回答

5

正如@AllanCameron所指出的那样,你需要的相当于取大小为12的vec的所有组合 -- 你还可以使用内置函数combn来实现这一点:

do.call(rbind, combn(vec, L, simplify = FALSE))

使用 data.table 可能会更快地将 combn 的输出转换为所需的格式:

library(data.table)
setDT(transpose(combn(vec, L, simplify=FALSE))

1
我猜这里应该使用rev(vec),因为OP“仅需要第一列中的值大于第二列中的值,第二列中的值大于第三列中的值,依此类推”的组合。 - ThomasIsCoding
@ThomasIsCoding 是的没错!或者,我们可以将 data.table 的解决方案分配为 x,然后执行 setcolorder(x, ncol(x):1) - MichaelChirico

3
您可以使用包中的函数轻松实现此操作:
result <- gtools::combinations(length(vec), L, vec)[, L:1]

这个函数本身会按照升序给出列名,因此子集仅用于正确排序。

这是一个大矩阵,因此需要一些时间,但在我的工作电脑上只需要大约5秒钟:

microbenchmark::microbenchmark(combinations(22, 12, 21:0)[,12:1], times = 5)
Unit: seconds
                              expr      min       lq     mean   median       uq      max neval
combinations(22, 12, 21:0)[, 12:1] 4.965595 5.211964 5.261557 5.249413 5.341981 5.538831     5

我们可以看到前五行给出了正确的格式:
result[1:5,]
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
#> [1,]   11   10    9    8    7    6    5    4    3     2     1     0
#> [2,]   12   10    9    8    7    6    5    4    3     2     1     0
#> [3,]   13   10    9    8    7    6    5    4    3     2     1     0
#> [4,]   14   10    9    8    7    6    5    4    3     2     1     0
#> [5,]   15   10    9    8    7    6    5    4    3     2     1     0

确认我们的尺寸正确:

dim(result)
#> [1] 646646     12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接