Расчет квантилей для больших данных

У меня есть около 300 файлов, каждый из которых содержит 1000 реализаций временных рядов (~ 76 МБ каждый файл).

Я хочу рассчитать квантили (0,05, 0,50, 0,95) на каждом временном шаге из полного набора из 300000 реализаций.

Я не могу объединить реализации в 1 файл, потому что он станет слишком большим.

Каков наиболее эффективный способ сделать это?

Каждая матрица создается путем запуска модели, однако вот образец, содержащий случайные числа:

x <- matrix(rexp(10000000, rate=.1), nrow=1000)

person Claudia    schedule 24.02.2014    source источник


Ответы (1)


Есть как минимум три варианта:

  1. Вы уверены, что он должен быть из полного комплекта? 10% выборка здесь должна быть очень хорошим приближением.
  2. 300 000 элементов — это не так уж и много для вектора, но матрица-столбец размером 300 000 x 100+ — это очень много. Вытащите в память только нужный вам столбец, а не всю матрицу (при необходимости можно повторить для каждого столбца).
  3. Do it sequentially, possibly in conjunction with a smaller sample to get you started in the right ballpark. For the 5th percentile, you just need to know how many items are above the current guess and how many are below. So something like:
    1. Take a 1% sample, find the 5th percentile of it. Jump some tolerance above and below, such that you're sure the exact 5th percentile lies in that range.
    2. Читать в матрице кусками. Для каждого фрагмента подсчитайте количество наблюдений выше диапазона и ниже диапазона. Затем сохраните все наблюдения, лежащие в пределах диапазона.
    3. Когда вы прочитали последний фрагмент, у вас теперь есть три фрагмента информации (счет вверху, счет внизу, вектор наблюдений внутри). Один из способов получить квантиль — отсортировать весь вектор и найти n-е наблюдение, и вы можете сделать это с приведенными выше фрагментами информации: отсортировать наблюдения в пределах диапазона и найти (n-count_below)th.

Изменить: пример (3).

Обратите внимание, что я не лучший разработчик алгоритмов и что кто-то почти наверняка разработал для этого лучший алгоритм. Кроме того, эта реализация не особенно эффективна. Если для вас важна скорость, рассмотрите Rcpp или даже более оптимизированный для этого R. Создавать кучу списков, а затем извлекать из них значения не так уж и умно, но прототипировать таким образом было легко, поэтому я пошел по этому пути.

library(plyr)

set.seed(1)

# -- Configuration -- #
desiredQuantile <- .25

# -- Generate sample data -- #

# Use some algorithm (sampling, iteration, or something else to come up with a range you're sure the true value lies within)
guessedrange <- c( .2, .3 )
# Group the observations to correspond to the OP's files
dat <- data.frame( group = rep( seq(100), each=100 ), value = runif(10000) )

# -- Apply the algorithm -- #

# Count the number above/below and return the values within the range, by group
res <- dlply( dat, .( group ), function( x, guessedrange ) {
  above <- x$value > guessedrange[2]
  below <- x$value < guessedrange[1]
  list(
    aboveCount  = sum( above ),
    belowCount = sum( below ),
    withinValues = x$value[ !above & !below ]
  )
}, guessedrange = guessedrange )
# Exract the count of values below and the values within the range
belowCount <- sum( sapply( res, function(x) x$belowCount ) )
belowCount
withinValues <- do.call( c, sapply( res, function(x) x$withinValues ) )
str(withinValues)
# Count up until we find the within value we want
desiredQuantileCount <- floor( desiredQuantile * nrow(dat) ) #! Should fix this so it averages when there's a tie
sort(withinValues)[ desiredQuantileCount - belowCount + 1 ]
# Compare to exact value
quantile( dat$value, desiredQuantile )

В конце концов, значение немного отличается от точной версии. Я подозреваю, что меня сбило с толку одно или какое-то столь же глупое объяснение, но, возможно, я упускаю что-то фундаментальное.

person Ari B. Friedman    schedule 24.02.2014
comment
Спасибо за Ваш ответ! 1. Мне нужно брать полный набор, потому что каждый файл является результатом другой модели, разные модели возвращают очень разные результаты. 2. Каждый столбец представляет временной шаг, поэтому мне нужны все столбцы. 3. Я правильно понимаю, что этот метод возвращает хорошие приблизительные значения, но не точные, верно? - person Claudia; 24.02.2014
comment
(3) должно быть точным. Но смысл (1) в том, что вы можете попробовать. Итак, загрузите каждый файл, выберите 1 или 5% его строк, загрузите следующий файл. Радости рандомизации означают, что ответ, который вы получите, будет чрезвычайно близок к точной версии. - person Ari B. Friedman; 25.02.2014
comment
В (3) должны быть разные диапазоны (тем более, что модели разные), поэтому вы не можете просто наивно сортировать все собранные данные внутри диапазона вместе: они не выровнены. Нужно обнаружить пересечение всех диапазонов (задавая по одному поддиапазону), а затем уже там можно провести сортировку, но тогда вычисление квантилей все же не так сразу, так как каждый поддиапазон имеет разный сдвиг (это квантили, исходящие из РАЗНОЙ вероятности). интервалы!). Если учесть все это и неопределенность выборки в диапазонах, алгоритм должен работать нормально. - person Quartz; 25.02.2014
comment
@Quartz Думаю, я не совсем ясно объяснил свое намерение. Цель состоит в том, чтобы использовать небольшую выборку всех данных для оценки диапазона, в котором, как вы уверены, находится точное значение. Затем используйте этот диапазон. Я отредактирую, чтобы проиллюстрировать. - person Ari B. Friedman; 25.02.2014