对于二变量问题,outer
很可能是最好的解决方案,如果循环的空间足够小,那么我们可以有 expand.grid
做我们的跑腿工作。然而,如果我们有两个以上的变量和一个大的空间来循环,这些就被排除了。 outer
不能处理两个以上的变量和 expand.grid
占用的内存比我见过的机器能够占用的内存还多。
我最近发现自己在写这样的代码:
n<-1000
for(c in 1:n){
for(b in 1:c){
for(a in 1:b){
if(foo(a,b,c))
{
bar(a,b,c)
}
}
}
}
在这些情况下,嵌套循环似乎是自然的解决方案(例如
mapply
不会做,并且 tapply
没有好的因素可以使用),但是有更好的方法吗?这似乎是通往错误代码的道路。我怀疑
combn
也许能够以某种方式做到这一点,但根据我的经验,它很快就会陷入与 expand.grid
相同的内存陷阱中。 .如果没记错的话,我也知道它采取了不明智的步骤,告诉我更改递归限制的全局设置。
最佳答案
这是与重复的组合。 rcppalgos可能是您开箱即用的最佳选择,但在 n = 1000L
,这只是超过 5 亿个组合,将占用 ~ 2GB 的内存。
library(RcppAlgos)
n = 1000L
mat <- comboGeneral(n, 3L, repetition = TRUE)
现在有两条路要走。如果您有 RAM 并且您的函数能够被矢量化,那么您可以非常快速地完成上述操作。假设组合的总和大于 1000,您需要组合的均值,否则您需要组合的总和。
res <- if (rowSums(mat) > 1000L)
rowMeans(mat)
else
rowSums(mat)
## Error: cannot allocate vector of size 1.2 Gb
不好了!我得到了可怕的分配向量错误。 rcppalgos允许您返回函数的结果。但请注意,它返回一个列表并且速度要慢得多,因为它将不得不评估您的 R 函数,而不是停留在 C++ 中。为此,我改成了
n = 100L
因为我没有一整天...comboGeneral(100L, 3L, repetition = TRUE,
FUN = function(x) {
if (sum(x) > 100L)
mean(x)
else
sum(x)
}
)
如果我有一个静态集合,我总是从
n
中选择 3 个组合,我可能会使用 Rcpp
代码直接取决于什么foo(a,b,c)
和 bar(a,b,c)
是,但首先我想了解更多有关这些功能的信息。
关于r - 如何避免为大型数据集编写嵌套的 for 循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62225190/