Графики больших объемов данных

в настоящее время мы используем ZedGraph для рисования графика ряда данных. Входные данные поступают из файла произвольного размера, поэтому мы заранее не знаем, какое максимальное количество точек данных. Однако, открыв файл и прочитав заголовок, можно узнать, сколько точек данных в файл.

формат файла по существу [time (double), value (double)]. Однако записи не являются однородными по оси времени. Между словами t = 0 не может быть никаких точек сек и t = 10 сек, но между t = 10 сек и t = 11 сек может быть 100k и так далее.

в качестве примера, наш файл тестового набора данных ~2.6 GB и имеет 324m точек. Мы хотели бы показать весь график пользователю и позволить ей перемещаться по диаграмме. Однако загрузка точек 324M в ZedGraph не только невозможна (мы находимся на 32-битной машине), но и не полезна, поскольку нет смысла иметь так много точек на экране.

использование FilteredPointList функция ZedGraph также не подлежит сомнению, поскольку для этого требуется сначала загрузить все данные, а затем выполнить фильтрацию по этим данным.

Итак, если мы ничего не упускаем, кажется, что наше единственное решение-каким-то образом уничтожить данные, однако, когда мы продолжаем работать над этим, мы сталкиваемся с множеством проблем:

1-Как мы уничтожаем данные, которые не поступают равномерно во времени?

2 - поскольку все данные не могут быть загружены в память, любой алгоритм должен работать на диске и поэтому должен быть тщательно продуман.

3 - Как мы обрабатываем масштабирование, особенно, когда данные неоднородны по оси X.

Если бы данные были однородными, при начальной загрузке графика мы могли бы Seek() по предопределенному количеству записей в файле, и выбрать каждый N других образцов и передать его в ZedGraph. Однако, поскольку данные неоднородны, мы должны быть более разумными в выборе образцов для отображения, и мы не могу придумать никакого интеллектуального алгоритма, который не должен был бы читать весь файл.

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

мы находимся на 32-разрядной версии Windows, .NET 4.0.

4 ответов


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

в основном вам нужно получить диапазон данных (минимальные и максимальные возможные/необходимые значения Индекса), разделить на сегменты (скажем, 100 сегментов), а затем определить значение для каждого сегмента по некоторому алгоритму (среднее значение, медианное значение и т. д.). Тогда вы заговор на основе тех обобщены 100 элементов. Это намного быстрее, чем пытаться построить миллионы точек :-).

Итак, то, что я говорю, похоже на то, что вы говорите. Вы упоминаете, что не хотите строить все элементы X, потому что между элементами может быть длинный промежуток времени (значения индекса на оси x). Я говорю о том, что для каждого подразделения данных определите, что является лучшим значением, и возьмите это как точку данных. Мой метод основан на значении индекса, поэтому в вашем примере нет данных между значения Индекса 0 sec и 10 sec я бы все равно поместил туда точки данных, они просто имели бы одинаковые значения между собой.

дело в том, чтобы суммировать данные, прежде чем строить его. Продумывать свои алгоритмы, чтобы сделать это аккуратно, есть много способов сделать это, выберите тот, который работает для вашего приложения.

вы можете уйти, не написав свой собственный компонент графика и просто написать алгоритм суммирования данных.


Я бы подошел к этому в два этапа:

  1. предварительная обработка данных
  2. отображение данных

Шаг 1 Файл должен быть предварительно обработан в двоичный файл фиксированного формата. Добавление индекса в формат, это будет int, double, double. См. эту статью для сравнения скорости:

http://www.codeproject.com/KB/files/fastbinaryfileinput.aspx

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

1,1/27/2011 8:30:00
13456,1/27/2011 9:30:00

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

Шаг 2 Способы отображения данных 1. Просто покажите каждую запись по индексу. 2. Нормализация данных и создание агрегированных баров данных с открытыми, высокими ,низкими и близкими значениями. а. По Времени б. По количеству записей c. По разнице между значением

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


1-Как мы уничтожаем данные, которые не прибытие равномерно во времени?

(Примечание - Я предполагаю, что ваш файл данных загрузчика находится в текстовом формате.)

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

Как только данные были в базе данных, мы могли легко сортировать их и количественно оценивать большие объемы данных в сингулярные перефразированные запросы (используя встроенные функции SQL summary, такие как SUM). MySQL мог даже прочитать свои результаты запроса обратно в текстовый файл для использования в качестве данных загрузчика.

короче говоря, потребляя этот объем данных требует использования инструмента, который может суммировать данные. MySQL подходит для счета (каламбур предназначен...это бесплатно).


относительно простой альтернативой, которую я нашел, чтобы сделать это, является следующее:

  1. перебирать данные в небольших группировках точек (скажем, от 3 до 5 точек за раз - чем больше группа, тем быстрее будет работать алгоритм, но тем менее точной будет агрегация).
  2. вычислить min & max небольшой группы.
  3. удалить все точки, которые являются не min или max из этой группы (т. е. вы держите только 2 балла от каждой группы и остальное опустить).
  4. продолжайте перебирать данные (повторяя этот процесс) от начала до конца, удаляя точки, пока агрегированный набор данных не будет иметь достаточно небольшого количества точек, где он может быть нанесен на карту без удушения ПК.

Я использовал этот алгоритм в прошлом, чтобы взять наборы данных ~10 миллионов точек до порядка ~5K точек без каких-либо очевидных видимых искажений графика.

идея здесь в том, что, выбрасывая очки, вы сохраняете пики и долины, поэтому "сигнал", просматриваемый на конечном графике, не "усредняется" (обычно, если усреднение, вы увидите, что пики и долины становятся менее заметными).

другим преимуществом является то, что вы всегда видите "реальные" точки данных на конечном графике (в нем отсутствует куча точек, но точки, которые есть на самом деле в исходном наборе данных, поэтому, если вы наведете курсор мыши на что-то, вы можете показать фактические значения x & y, потому что они реальны, а не усредненный.)

наконец, это также помогает с проблемой отсутствия последовательного интервала по оси x (опять же, у вас будут реальные точки вместо усреднения позиций по оси X).

Я не уверен, насколько хорошо этот подход будет работать с миллионами миллионов точек данных, как у вас, но, возможно, стоит попробовать.