r - 如何避免为大型数据集编写嵌套的 for 循环?
问题描述
对于一个二变量问题,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)
}
)
如果我有一个静态集合,我总是从 中选择 3 个组合n
,我可能会Rcpp
直接使用代码,具体取决于什么foo(a,b,c)
和bar(a,b,c)
是,但首先我想了解更多关于函数的信息。
推荐阅读
- python - 我有一个“开始日期”和“结束日期”列。我想把每一行变成 X 行,每个包含日期
- node.js - 如何使用 edit-json-file npm 读取和更新数组中的值
- jquery - 如何在jQuery.qrcode中动态设置文本的值
- ruby-on-rails - 用户能够看到所有者属性 Rails 5.2
- php - 如何从 Laravel 中的当前时间减去时间?
- mongodb - 检查goLang中的mongodb集合中是否存在数据?
- mysql - MySQL 查看聚合查询的性能问题
- vue.js - 使用nuxt部署后如何添加新的动态路由?
- swift - nil 签入用户默认值 (Swift 5)
- javascript - React Js Error Can't perform a React state update on an unmounted component