Интерполяция больших наборов данных на лету - PullRequest
9 голосов
/ 25 марта 2010

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

У меня есть большой набор данных около 0,5 млн. Записей, представляющих обменный курс между USD / GBP за определенный день.

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

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

Ура, Карл

Ответы [ 6 ]

4 голосов
/ 03 апреля 2010

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

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

Вот пример использования метода 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 представляют скорость и дистанцию.

3 голосов
/ 25 марта 2010

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

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-минутного интервала) или другая математическая функция для объединения подходящей группы вместо медианы. Учитывая сложность процедуры временного сегментирования и то, как ваша СУБД оптимизирует, может быть более эффективно выполнить запрос к временной таблице со значением сегментированного времени.

1 голос
/ 04 апреля 2010

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

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

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

1 голос
/ 02 апреля 2010

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

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

1 голос
/ 02 апреля 2010

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

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

0 голосов
/ 04 апреля 2010

Как насчет сделать перечисление / итератор оберткой. Я не знаком с 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);
    }
}
...