我有一个具有以下结构的数据集:
require(data.table)
train <- data.table(sample(1:10, 10), runif(10, 0, 10))
但是,数据集的内存约为7.5 GB,并具有约6.3亿行。尝试summary(train)
会产生错误:Error: cannot allocate vector of size 2.3 Gb
。我可以通过手动调用train[, mean(V2)]
,train[, min(V2)]
和train[, max(V2)]
来提取一些信息,但是中位数和分位数会导致OOM。是否可以在16GB RAM机器上进行这些操作?
一个想法是分割数据集,但是这对于中位数和分位数来说比较麻烦
答案 0 :(得分:1)
所以我想出了函数summaryI
,我们在其中提供了感兴趣的列名:
summaryI <- function(i2) {
setorderv(train, i2)
N <- train[, .N]
# count NAs:
# nas <- is.na(train[[i2]])
# nNA <- sum(nas)
# OR
i <- 1L
nNA <- 0L
while (is.na(train[[i2]][i])) {
nNA <- nNA + 1L
i <- i + 1L
}
nNA
# will be slow if many NAs, but more memory efficient
# (will not create additional vector)
n <- N - nNA
probs <- seq(0, 1, 0.25)
# quantiles, only type = 7
index <- 1 + (n - 1) * probs
lo <- floor(index)
hi <- ceiling(index)
qs <- train[[i2]][lo + nNA]
i <- which(index > lo)
h <- (index - lo)[i]
qs[i] <- (1 - h) * qs[i] + h * train[[i2]][hi[i] + nNA]
qs # quantile results
rmean <- sum(train[[i2]], na.rm = T) / n
qq <- c(qs[1L:3L], rmean, qs[4L:5L])
digits <- max(3L, getOption("digits") - 3L)
qq <- signif(qq, digits)
names(qq) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", "Max.")
if (nNA > 0L) { # to match summary output
c(qq, `NA's` = nNA)
} else {
qq
}
}
基本思想是,我们将感兴趣的列(从setorder
开始使用data.table
进行排序,然后尝试执行所有计算而不复制数据。
如评论中所述,如果您的数据具有很多NA,那么这将很慢。 但是希望您能够在所有数据上运行。另外,我在NA管理内部进行了硬编码。
示例:
summaryI('V2')
# Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
# 2.398e-08 2.501e-01 5.000e-01 5.000e-01 7.500e-01 1.000e+00 1.000e+02
或遍历多个列,例如:
sapply(colnames(train), summaryI)
我作为基础的summary
和quantile
的源代码可以找到: