R-比循环效率较低



我试图在大表上进行此操作,以在数据中使用A和B的不同组合计数。Tablex。

Y <- aggregate(c ~ a+b,X,length)

这是永远花的(我在30分钟后停止),尽管RAM使用量仍在。

然后,我尝试手动循环通过b的值并仅在a上进行汇总(从技术上讲仍在b上汇总,但每次都以b为单一值):

sub_agg <- list()
unique_bs <- unique(X$b)
for (b_it in unique_bs){
sub_agg[[length(sub_agg)+1]] <- aggregate(c ~ a + b,subset(X, b == b_it),length)
}
Y <- do.call(rbind, sub_agg )

,我在3分钟内完成了。

我也可以走得更远,完全摆脱了总体,只有在子集上进行操作。

总体效率不如嵌套环和子集上的操作效率不高,或者这是一种特殊情况?

聚集通常是最花时间的代码部分,所以我现在正在考虑总是尝试循环,我想更好地理解这里发生的事情。

附加信息:

x有2000万行

B

的50个不同的值

的15 000个不同的值

是的,汇总的效率不如您在那里使用的循环,因为:

  • 当数据点数量增加时,聚集体的速度降低了。您的第二个解决方案在小子集上使用aggregate。中的一个原因是aggregate取决于排序,并且在O(n)时间中不进行排序。
  • 汇总还在内部使用expand.grid,该数据框架具有变量A和B中所有唯一值的所有可能组合。您可以在aggregate.data.frame的内部代码中看到这一点。同样,随着观察次数的增加,此功能变得越来越慢。
  • 编辑:我的最后一点并没有真正有意义

也就是说,这里绝对没有理由在这里使用aggregate。我只需使用table即可进入数据框Y

thecounts <- with(X, table(a,b))
Y <- as.data.frame(thecounts)

此解决方案比使用aggregate提出的解决方案要快得多。准确地说我的机器上有68次...

基准:

        test replications elapsed relative 
1  aggloop()            1   15.03   68.318 
2 tableway()            1    0.22    1.000 

基准测试的代码(请注意,我使所有内容都稍小一点,以免阻止我的r太长):

nrows <- 20e5
X <- data.frame(
  a = factor(sample(seq_len(15e2), nrows, replace = TRUE)),
  b = factor(sample(seq_len(50), nrows, replace = TRUE)),
  c = 1
)
aggloop <- function(){
sub_agg <- list()
unique_bs <- unique(X$b)
for (b_it in unique_bs){
  sub_agg[[length(sub_agg)+1]] <- aggregate(c ~ a + b,subset(X, b == b_it),length)
}
Y <- do.call(rbind, sub_agg )
}
tableway <- function(){
  thecounts <- with(X, table(a,b))
  Y <- as.data.frame(thecounts)
}
library(rbenchmark)
benchmark(aggloop(),
          tableway(),
          replications = 1
          )

@jorismeys的建议,并说明我的评论,这是实现您所追求的一种方法的另一种方法。

data.table语法的一般形式是, DTdata.tableDT[i, j, by],含义"取dt,使用i的子集行,然后计算j,由"
分组)例如,X中的每个ab级别获得计数的代码为:X[, .N, by=c("a", "b")]

您可以在本软件包简介中阅读有关data.table的更多信息。

如果我们想使用相同的示例数据X和Jorismeys中定义的函数进行其他方式基准data.table

library(data.table)
X2 <- copy(X) # taking a copy of X so the conversion to data.table does not impact the initial data
dtway <- function(){
            setDT(X2)[, .N, by=c("a", "b")] # setDT permits to convert X2 into a data.table
         }
library(rbenchmark)
benchmark(aggloop(),
          tableway(),
          dtway(),
          replications = 1)
        # test replications elapsed relative
# 1  aggloop()            1   17.29  192.111
# 3    dtway()            1    0.09    1.000
# 2 tableway()            1    0.27    3.000

注意:效率取决于数据,我尝试了几个X(具有不同的随机种子),并发现data.table相对于base table,CC_24的相对效率从1/2.5到1/3.5。

最新更新