Интерполяция больших наборов данных на лету

Интерполяция больших наборов данных

У меня есть большой набор данных приблизительно 0,5 миллионов записей, представляющих обменный курс между долларом США / фунт стерлингов в течение данного дня.

У меня есть приложение, которое хочет смочь изобразить в виде графика эти данные или возможно подмножество. По очевидным причинам я не хочу выводить 0,5 миллиона на печать точек на моем графике.

То, в чем я нуждаюсь, является меньшим набором данных (приблизительно 100 точек), который точно (как возможный) представляет определенные данные. Кто-либо знает о каких-либо интересных и производительных способах, которыми могут быть достигнуты эти данные?

С наилучшими пожеланиями, Karl

9
задан Karl 25 March 2010 в 11:11
поделиться

6 ответов

Одна мысль - использовать СУБД для сжатия данных с помощью соответствующего запроса. Что-то вроде того, что требуется медиана для определенного диапазона, псевдозапрос:

SELECT truncate_to_hour(rate_ts), median(rate) FROM exchange_rates 
WHERE rate_ts >= start_ts AND rate_ts <= end_ts
GROUP BY truncate_to_hour(rate_ts)
ORDER BY truncate_to_hour(rate_ts)

Где truncate_to_hour - это что-то подходящее для вашей СУБД. Или аналогичный подход с какой-то функцией для сегментации времени на уникальные блоки (например, округление до ближайшего 5-минутного интервала) или другой математической функцией для агрегирования группы, которая подходит вместо медианы. Учитывая сложность процедуры сегментирования по времени и то, как ваша СУБД оптимизирует, может быть более эффективным выполнить запрос к временной таблице с сегментированным значением времени.

3
ответ дан 4 December 2019 в 21:09
поделиться

Если бы вы хотели написать свой собственный, одним из очевидных решений было бы разбить свой рекорд, установленный на фиксированные куски с количеством точек, для которых значение будет средним (среднее, медианное, ... выберите один). Это имеет вероятное преимущество в том, что он самый быстрый, и показывает общие тенденции.

Но ему не хватает драмы ценовых тиков. Лучшим решением, вероятно, будет поиск точек перегиба, а затем выбор среди них с помощью раздвижных окон. Это имеет преимущество в том, что лучше отображает фактические события дня, но будет медленнее.

1
ответ дан 4 December 2019 в 21:09
поделиться

Что-то вроде RRDTool сделает то, что вам нужно, автоматически - учебник должен помочь вам начать работу, а drraw построит график данных.

Я использую это на работе для таких вещей, как графики ошибок, мне не нужно 1-минутное разрешение для 6-месячного периода времени, только для последних нескольких часов. После этого у меня есть 1-часовое разрешение на несколько дней, а затем 1-дневное разрешение на несколько месяцев.

1
ответ дан 4 December 2019 в 21:09
поделиться

Существует несколько статистических методов сокращения большого набора данных до меньшего, более простого для визуализации набора данных. Из вашего вопроса неясно, какая сводная статистика вам нужна. Я просто предположил, что вы хотите увидеть, как меняется обменный курс во времени, но, возможно, вас интересует, как часто обменный курс превышает определенное значение, или какой-либо другой статистический показатель, который я не рассматриваю.

Обобщение тенденции во времени

Вот пример использования метода lowess в R (из документации по сглаживанию графика рассеяния ):

> library(graphics)
# print out the first 10 rows of the cars dataset
> cars[1:10,]
   speed dist
1      4    2
2      4   10
3      7    4
4      7   22
5      8   16
6      9   10
7     10   18
8     10   26
9     10   34
10    11   17

# plot the original data
> plot(cars, main = "lowess(cars)")
# fit a loess-smoothed line to the points
> lines(lowess(cars), col = 2)
# plot a finger-grained loess-smoothed line to the points
> lines(lowess(cars, f=.2), col = 3)

Параметр f контролирует, насколько точно регрессия соответствует вашим данным. Проявите некоторую вдумчивость в этом вопросе, так как вам нужно что-то, что точно соответствует вашим данным, но не переоснащается. Вместо скорости и расстояния вы можете построить график зависимости обменного курса от времени.

Также просто получить доступ к результатам сглаживания. Вот как это сделать:

> data = lowess( cars$speed, cars$dist )
> data
$x
 [1]  4  4  7  7  8  9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 16 16 17 17 17 18 18 18 18 19 19
[38] 19 20 20 20 20 20 22 23 24 24 24 24 25

$y
 [1]  4.965459  4.965459 13.124495 13.124495 15.858633 18.579691 21.280313 21.280313 21.280313 24.129277 24.129277
[12] 27.119549 27.119549 27.119549 27.119549 30.027276 30.027276 30.027276 30.027276 32.962506 32.962506 32.962506
[23] 32.962506 36.757728 36.757728 36.757728 40.435075 40.435075 43.463492 43.463492 43.463492 46.885479 46.885479
[34] 46.885479 46.885479 50.793152 50.793152 50.793152 56.491224 56.491224 56.491224 56.491224 56.491224 67.585824
[45] 73.079695 78.643164 78.643164 78.643164 78.643164 84.328698

Возвращаемый вами объект данных содержит записи с именами x и y, которые соответствуют значениям x и y, переданным в функцию lowess. В этом случае x и y обозначают скорость и расстояние.

4
ответ дан 4 December 2019 в 21:09
поделиться

Наивный подход заключается в простом вычислении среднего значения за интервал времени, соответствующий пикселю.

http://commons.wikimedia.org/wiki/File:Euro_exchange_rate_to_AUD.svg

Это не показывает колебания. Я бы предложил также рассчитать стандартное отклонение в каждом временном интервале и построить его тоже (по сути, делая каждый пиксель выше одного пикселя). Мне не удалось найти пример, но я знаю, что Gnuplot может это сделать (но не написан на Java).

1
ответ дан 4 December 2019 в 21:09
поделиться

Как насчет создания оболочки перечисления / итератора. Я не знаком с Java, но он может выглядеть примерно так:

class MedianEnumeration implements Enumeration<Double>
{
    private Enumeration<Double> frameEnum;
    private int frameSize;

    MedianEnumeration(Enumeration<Double> e, int len) {
        frameEnum = e;
        frameSize = len;
    }

    public boolean hasMoreElements() {
        return frameEnum.hasMoreElements();
    }

    public Double nextElement() {
        Double sum = frameEnum.nextElement();

        int i;
        for(i=1; (i < frameSize) && (frameEnum.hasMoreElements()); ++i) {
            sum += (Double)frameEnum.nextElement();
        }

        return (sum / i);
    }
}
0
ответ дан 4 December 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: