Ускорьте ListLinePlot - PullRequest
8 голосов
/ 03 июля 2011

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

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

1309555993069, -2.369941, 6.129157, 6.823794
1309555993122, -2.260978, 6.170018, 7.014479
1309555993183, -2.070293, 6.129157, 6.823794
1309555993242, -1.988571, 6.238119, 7.123442

В одном файле данных содержится до 2 · 10 6 строк.Например, для отображения второго столбца я использую:

x = Import["path/to/datafile"];
ListLinePlot[x[[All, {1, 2}]]]

Время выполнения этой операции невыносимо велико.Чтобы отобразить переменный диапазон данных, я пытался использовать Manipulate:

Manipulate[ListLinePlot[Take[x, numrows][[All, {1, 2}]]], {numrows, 1, Length[x]}]

Эта инструкция работает, но она быстро сканируется, когда я пытаюсь отобразить более нескольких тысяч строк.Как я могу ускорить его?

Некоторые дополнительные сведения:

  • MATLAB отображает одинаковый объем данных на одном компьютере практически мгновенно, поэтому размер необработанных данных не должен бытьпроблема.
  • Я уже пытался отключить сглаживание графики, но это никак не повлияло на скорость рендеринга.
  • Использование DataRange во избежание Take не помогает.
  • Использование MaxPlotPoints искажает слишком много сюжета, чтобы быть полезным.
  • Не использовать Take в Manipulate не помогает.
  • Рендеринг, кажется, занимает огромное количествовремени.Запуск Timing[ListLinePlot[Take[x,100000][[All, {1, 2}]]]] возвращает 0.33: это означает, что оценка Take сама по себе является почти мгновенной, это рендеринг графика, который все замедляет.
  • Я запускаю Mathematica на Ubuntu Linux 11.10 с использованием fglrxводители.Заставить Mathematica использовать драйверы Mesa не помогло.

Есть подсказка?

Ответы [ 4 ]

11 голосов
/ 08 июля 2011

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

Я разбиваю данные на несколько блоков, примерно соответствующих разрешению моего экрана (обычно 1000 или меньше), в любом случае больше деталей отображать невозможно.Затем я определяю минимальное и максимальное значения каждого блока и рисую зигзагообразную линию от минимума до максимума, от минимума до максимума ... Результат будет выглядеть точно так же, как исходные данные.Однако вы не можете «увеличить», как тогда, когда вы увидите зигзагообразную линию (например, при экспорте в PDF с высоким разрешением).Затем вам нужно использовать большее количество блоков.

rv = RandomVariate[ExponentialDistribution[2], 100000];

ListLinePlot[rv, PlotRange -> All] (* original, slow *)
ListLinePlot[rv, PlotRange -> All, MaxPlotPoints -> 1000] (* fast but distorted *)

numberOfBlocks = 1000;

ListLinePlot[Riffle @@ Through[{Min /@ # &, Max /@ # &}[
   Partition[rv,Floor[Length[rv]/numberOfBlocks]]]], PlotRange -> All]

Вы можете добавить опцию DataRange->{...}, чтобы соответствующим образом пометить ось X.

Надеюсь, это поможет!

РЕДАКТИРОВАТЬ: См. Также этот похожий вопрос на Mathematica Stackexchange: https://mathematica.stackexchange.com/q/140/58

7 голосов
/ 03 июля 2011

Я не тестировал это на своей машине (у меня Mac, поэтому я не могу исключить проблемы, связанные с Linux). но пара моментов происходит со мной. Следующее было довольно быстро для меня, но, очевидно, медленнее, чем если бы набор данных был меньше. Вы строите сотни тысяч точек данных.

data = Accumulate@RandomVariate[NormalDistribution[], 200000];
Manipulate[ListLinePlot[Take[data, n]], {n, 1, Length[data]}]
  1. В Manipulate вы разрешаете произвольно варьировать количество данных, показанных с помощью Take. Попробуйте только увеличивать numrows каждые 100 или около того пунктов, чтобы меньше отображалось.
  2. Попробуйте использовать опцию ContinuousAction->False (см. документация ) (я вижу, @Szabolcs имел ту же идею, что и я печатал.
  3. Я собирался предложить MaxPlotPoints, но вместо этого попробуйте вариант PerformanceGoal ->"Speed". (см. документация )
5 голосов
/ 26 июля 2011

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

5 голосов
/ 03 июля 2011

Я также заметил, что иногда Mathematica будет слишком долго отображать графику. На самом деле это должен быть некоторый шаг перевода из выражения Mathematica Graphics в другое представление, которое занимает много времени, потому что после рендеринга изменение размера (и, следовательно, повторное рендеринг) графики происходит намного быстрее. Рендеринг графики до версии 6 раньше был быстрее во многих примерах (но при этом не хватает функциональности, которая есть у 6+).

Некоторые идеи о том, что вы могли бы сделать:

  1. Используйте параметр MaxPlotPoints ListLinePlot, чтобы уменьшить данные перед построением графика. Это может не иметь значения во взглядах, если его пониженная выборка. Опция Method должна выбирать алгоритм даунсамплинга, но я не могу найти какие-либо документы для него (кто-нибудь?)

  2. Используйте ContinuousAction -> False в Manipulate, чтобы остановить пересчет всего в реальном времени при перетаскивании ползунков.

...