您的问题有两个部分,高效计算和处理大数据。
高效计算
假设您有一个更易于管理的数据集m
,其中包含 3000 万行和 50 列中的 5%(这大约占我 8Gb 的 30%;内存不足会使一切运行缓慢,所以您需要让我们知道这种类型的信息)。
nrow <- .05 * 30000000
ncol <- 50
m <- matrix(rnorm(nrow * ncol), nrow)
也许您会编写一个函数clean
来有效地逐行删除异常值;它可能使用另一个有效计算逐行标准差的函数
rowSD <- function(m) {
## efficiently calculate row-wise SD
## naive: apply(m, 1, sd, na.rm=TRUE)
## update via @BenBolker / http://stackoverflow.com/questions/16046820/change-row-values-to-zero-if-less-than-row-standard-deviation
sqrt(rowSums((m - rowMeans(m, na.rm=TRUE))^2, na.rm=TRUE) / (ncol(m)-1))
}
clean <- function(m) {
## efficiently implement your strategy for identifying outliers
m[abs(m - rowMeans(m)) > 3 * rowSD(m)] <- NA # fast enough
m
}
对于矩阵m
,天真的实现rowSD(m)
大约需要 56 秒,而来自@BenBolker 的更新大约需要 1.4 秒;clean(sd)
大约需要5s。两者都制作数据的多个副本并传递数据,远非理想。
大数据
考虑以大块的形式处理您的数据nrow
。如果你清理了两个块m1
,m2
你可以将它们组合起来并保持最高值
sd <- c(rowSD(m1), rowSD(m2))
## if sorted, sd[idx] would be the value that separate high and low
idx <- nrow(result) + nrow(m) - nrow
keep <- sd > sort.int(sd, partial=idx)[idx] # index correct, or off-by-one?
## replace smallest in m1 with largest in m2
m1[!head(keep, nrow(m1)),] <- m2[tail(keep, nrow(m2)),]
由于您正在执行矩阵运算,因此听起来您的数据都是数字,并且scan
以块的形式读取文件是适当的输入。
conn <- file("myfile", "r")
result <- matrix(0, nrow, ncol)
while (length(x <- scan(con, nmax = nrow * ncol))) {
m <- clean(matrix(x, nrow, ncol, byrow=TRUE))
sd <- c(rowSD(result), rowSD(m))
idx <- nrow(result) + nrow(m) - nrow
keep <- sd > sort.int(sd, partial=idx)[idx]
result[!head(keep, nrow),] <- m[tail(keep, nrow(m)),]
}
close(conn)
result
然后是具有最高标准偏差的清理行的期望集合。