Графические массивы данных
В настоящее время мы используем ZedGraph для построения линейной диаграммы некоторых данных. Входные данные поступают из файла произвольного размера, поэтому мы не знаем, какое максимальное количество данных должно быть заранее. Однако, открыв файл и прочитав заголовок, мы можем узнать, сколько точек данных находится в файле.
Формат файла по существу [time (double), value (double)]. Однако записи не являются равномерными по временной оси. Между точками t = 0 сек и t = 10 сек не должно быть точек, но может быть 100 К между t = 10 с и t = 11 сек и т.д.
В качестве примера наш тестовый файл набора данных составляет ~ 2.6 ГБ, и он имеет 324 М точек. Мы хотели бы показать весь график пользователю и позволить ей перемещаться по диаграмме. Однако загрузка 324M точек в ZedGraph не только невозможна (мы на 32-битной машине), но и не полезна, так как нет смысла иметь так много точек на экране.
Использование функции FilteredPointList для ZedGraph также представляется непостижимым, поскольку для этого требуется сначала загрузить все данные, а затем выполнить фильтрацию этих данных.
Итак, если мы ничего не пропустили, похоже, что наше единственное решение - как-то - уничтожить данные, однако по мере того, как мы продолжаем работать над этим, мы сталкиваемся с множеством проблем:
1- Как мы уничтожаем данные, которые не поступают равномерно по времени?
2- Поскольку все данные не могут быть загружены в память, любой алгоритм должен работать на диске, поэтому его необходимо тщательно спроектировать.
3 Как мы обрабатываем увеличение и уменьшение масштаба, особенно, когда данные не однородны по оси x.
Если данные были единообразными, то при начальной загрузке графика мы могли бы Seek()
определить предопределенное количество записей в файле и выбрать каждый N других образцов и передать его в ZedGraph. Однако, поскольку данные неравномерны, мы должны быть более интеллектуальными в выборе образцов для отображения, и мы не можем придумать какой-либо интеллектуальный алгоритм, который не должен был бы читать весь файл.
Извиняюсь, так как вопрос не имеет четкой специфичности, но я надеюсь, что смогу объяснить природу и масштаб нашей проблемы.
Мы находимся в Windows 32-bit,.NET 4.0.
Ответы
Ответ 1
Мне это нужно раньше, и это нелегко сделать. Из-за этого я закончил писать свой собственный компонент графа. В итоге все оказалось лучше, потому что я применил все необходимые нам функции.
В основном вам нужно получить диапазон данных (минимальные и максимальные возможные/необходимые значения индекса), подразделить на сегменты (скажем, на 100 сегментов), а затем определить значение для каждого сегмента по некоторому алгоритму (среднее значение, медианное значение, и т.д.). Затем вы строите на основе тех суммированных 100 элементов. Это намного быстрее, чем пытаться построить миллионы очков: -).
То, что я говорю, похоже на то, что вы говорите. Вы упомянули, что не хотите строить каждый элемент X, потому что между элементами может быть длинный отрезок времени (значения индекса по оси х). Я хочу сказать, что для каждого подразделения данных определить, что является лучшим значением, и считать это точкой данных. Мой метод основан на значении индекса, поэтому в вашем примере нет данных между значениями индекса 0 и 10 секунд я бы по-прежнему помещал туда данные, они имели бы одни и те же значения между собой.
Цель состоит в том, чтобы суммировать данные перед их построением. Подумайте над своими алгоритмами, чтобы сделать это внимательно, есть много способов сделать это, выберите тот, который работает для вашего приложения.
Возможно, вам не удастся написать свой собственный компонент графа и просто написать алгоритм суммирования данных.
Ответ 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. Нормализовать данные и создать совокупные бары данных с открытыми, высокими, низкими, близкими значениями. а. По времени б. По количеству записей с. Diff между значением
Для более возможных способов объединения неравномерных наборов данных вы можете посмотреть
различные методы, используемые для агрегирования данных о торговле на финансовых рынках. Конечно,
для скорости в режиме реального времени вы хотите создать файлы с этими данными уже
агрегируются.
Ответ 3
1- Как мы уничтожаем данные, которые не являются поступающих равномерно во времени?
( Примечание. Я предполагаю, что ваш файл данных загрузчика находится в текстовом формате.)
В аналогичном проекте мне пришлось читать файлы данных размером более 5 ГБ. Единственный способ, которым я мог разобрать это, - это прочитать его в таблице РСУБД. Мы выбрали MySQL, потому что он делает импорт текстовых файлов в datatables простым и простым. (Интересно в сторону - я был на 32-битной машине Windows и не мог открыть текстовый файл для просмотра, но MySQL не стал читать его без проблем.) Другой перк был MySQL кричал, кричал быстро.
Как только данные были в базе данных, мы могли бы легко отсортировать их и количественно определить большие объемы данных в синхронные перефразируемые запросы (используя встроенные SQL-сводные функции, такие как SUM
). MySQL мог даже прочитать результаты своих запросов обратно в текстовый файл для использования в качестве данных загрузчика.
Короче говоря, потребляя столько данных, требуется использование инструмента, который может суммировать данные. MySQL подходит для счета (каламбур... он бесплатный).
Ответ 4
Относительно простая альтернатива, которую я нашел, заключается в следующем:
- Итерации через данные в небольших точечных группировках (скажем, от 3 до 5 точек за раз - чем больше группа, тем быстрее алгоритм будет работать, но тем точнее будет агрегация).
- Вычислить min и max небольшой группы.
- Удалите все точки, которые не являются min или max из этой группы (т.е. вы сохраняете только 2 точки из каждой группы и опускаете остальные).
- Продолжайте циклически перебирать данные (повторяя этот процесс) от начала до конца, удаляя точки, пока совокупный набор данных не будет иметь достаточно малого количества точек, где он может быть начерчен без удушения ПК.
Я использовал этот алгоритм в прошлом, чтобы получить наборы данных ~ 10 миллионов точек до порядка ~ 5 тысяч точек без видимых видимых искажений на графике.
Идея здесь заключается в том, что, выкидывая точки, вы сохраняете пики и долины, поэтому "сигнал", просматриваемый на конечном графике, не "усредняется" (обычно, если усреднение, вы увидите пики и долины становятся менее заметными).
Другим преимуществом является то, что вы всегда видите "реальные" точки данных на конечном графике (он пропускает кучу точек, но точки, которые были там, были фактически в исходном наборе данных, поэтому, если вы что-то наводите на что-то, вы могут показывать фактические значения x и y, потому что они реальны, а не усреднены).
Наконец, это также помогает решить проблему отсутствия согласованного расстояния по оси x (опять же, вместо усреднения позиций X-Axis у вас будут реальные точки).
Я не уверен, насколько хорошо этот подход будет работать с 100 миллионами данных, например, у вас есть, но, возможно, стоит попробовать.