【问题标题】:Memory efficient way to print summary of dataset打印数据集摘要的内存有效方法
【发布时间】:2019-06-09 10:38:47
【问题描述】:

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

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

【问题讨论】:

  • sapply(train, summary) ?
  • 或者一次处理一个向量。您还可以考虑将数值变量存储为矩阵,然后使用 bigmemory 包来计算此类统计数据。
  • @YalDan 反馈?
  • 抱歉回复晚了,进行了 2 天的数字排毒,没有看到您为此付出的惊人努力 sapply(train, summary) 给了我完全相同的 OOM 消息,但这个想法是我的目标也是如此。 @Imo 我相信这就是@minem 和sapply 的解决方案无论如何都会做的对吗?关于bigmemory 包:加载数据非常缓慢,但我能够获得medianminmax 值。不幸的是,分位数会导致 OOM。此外,虽然比ff 慢,但我更喜欢它,因为它更易于使用。我现在会检查你的答案@minem,谢谢!

标签: r performance memory-management bigdata


【解决方案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
    }
} 

基本思想是我们将感兴趣的列排序(使用data.table 中的setorder),然后尝试在不复制数据的情况下进行所有计算。

如 cmets 中所述,如果您的数据有很多 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

【讨论】:

  • 我能说什么...这太棒了,在不到五分钟的时间内为我提供了列的摘要,这比使用大内存包要快得多。检查结果的有效性:~~~&gt; train &lt;- data.table(1:100, 1:100)&gt; summary(train$V1)Min. 1st Qu. Median Mean 3rd Qu. Max. 1.00 25.75 50.50 50.50 75.25 100.00&gt; summaryI('V1')Min. 1st Qu. Median Mean 3rd Qu. Max. 1.00 25.75 50.50 50.50 75.25 100.00 ~~~显然他们也是这样做的!希望我能给你一个以上的支持,非常感谢你的努力!
  • 对不起,代码格式看起来很糟糕,无论如何只是想强调一下结果确实是真实的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
  • 2016-01-04
  • 2022-11-20
  • 2014-04-14
  • 2013-06-20
  • 1970-01-01
相关资源
最近更新 更多