Эффективный для памяти способ распечатать сводку данных - PullRequest
0 голосов
/ 15 января 2019

У меня есть набор данных со следующей структурой:

require(data.table)
train <- data.table(sample(1:10, 10), runif(10, 0, 10))

Однако набор данных имеет размер ~ 7,5 ГБ в памяти и ~ 630 миллионов строк. Попытка summary(train) приводит к ошибке: Error: cannot allocate vector of size 2.3 Gb. Я могу извлечь некоторую информацию, вручную позвонив train[, mean(V2)], train[, min(V2)] и train[, max(V2)], но медиана и квантили приведут к OOM. Есть ли возможность выполнять эти операции на машине с 16 ГБ ОЗУ? Идея состояла бы в том, чтобы разделить набор данных, но это было бы немного громоздко по отношению к медиане и квантилям

1 Ответ

0 голосов
/ 15 января 2019

Итак, я придумал функцию 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, который я использовал в качестве основы, можно найти:

GitHub Quantile.R

github summary.R

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...