内存有效的方式来打印数据集摘要

时间:2019-01-15 12:06:35

标签: r performance memory-management bigdata

我有一个具有以下结构的数据集:

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机器上进行这些操作? 一个想法是分割数据集,但是这对于中位数和分位数来说比较麻烦

1 个答案:

答案 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)

我作为基础的summaryquantile的源代码可以找到:

github quantile.R

github summary.R