Итак, я придумал функцию 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