With big.matrix
对象,我发现了 2 个提供良好性能的解决方案:
- 根据您的具体需要,在 Rcpp 中编写一个函数。在这里,两个嵌套的 for 循环就可以解决问题。然而,您无法重新编码您需要的所有内容。
- 在您的列块上使用 R 函数
big.matrix
并汇总结果。它很容易做到并且仅使用 R 代码。
在您的情况下,列数增加 10,000 倍:
require(bigmemory)
x <- as.big.matrix(
matrix( sample(1:10, 20000, replace=TRUE), 5, 40000,
dimnames=list( NULL, rep(c("a", "b", "c", "d"), 10000) ) ) )
print(system.time(
true <- sqrt(colSums(x[,]^2))
))
print(system.time(
test1 <- biganalytics::apply(x, 2, function(x) {sqrt(sum(x^2))})
))
print(all.equal(test1, true))
So, colSums
速度非常快,但需要 RAM 中的所有矩阵,而biganalytics::apply
速度慢,但内存效率高。一个折衷方案是使用这样的东西:
CutBySize <- function(m, block.size, nb = ceiling(m / block.size)) {
int <- m / nb
upper <- round(1:nb * int)
lower <- c(1, upper[-nb] + 1)
size <- c(upper[1], diff(upper))
cbind(lower, upper, size)
}
seq2 <- function(lims) seq(lims["lower"], lims["upper"])
require(foreach)
big_aggregate <- function(X, FUN, .combine, block.size = 1e3) {
intervals <- CutBySize(ncol(X), block.size)
foreach(k = 1:nrow(intervals), .combine = .combine) %do% {
FUN(X[, seq2(intervals[k, ])])
}
}
print(system.time(
test2 <- big_aggregate(x, function(X) sqrt(colSums(X^2)), .combine = 'c')
))
print(all.equal(test2, true))
Edit:现在已经在包中实现了大统计:
print(system.time(
test2 <- bigstatsr::big_apply(x, a.FUN = function(X, ind) {
sqrt(colSums(X[, ind]^2))
}, a.combine = 'c')
))
print(all.equal(test2, true))