我正在尝试使用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]}]
此指令有效,但当我尝试显示超过几千行时,它会快速爬行。我怎样才能加快速度?
其他一些细节:
DataRange
来避免Take
无效。MaxPlotPoints
会过多地扭曲情节。Take
中不使用Manipulate
无效。Timing[ListLinePlot[Take[x,100000][[All, {1, 2}]]]]
会返回0.33
:这意味着Take
的评估本身几乎是即时的,是情节渲染会减慢所有内容。任何提示?
答案 0 :(得分:11)
如果您的目标是快速但正确地显示您的数据,您可以使用我经常使用的以下技巧。
我将数据划分为大致相当于我的屏幕分辨率的块数(通常为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
答案 1 :(得分:7)
我没有在我的机器上对此进行过广泛测试(我有一台Mac,所以我不能排除特定于Linux的问题)。但是我发现了几点。以下对我来说非常快,但明显比数据集较小时要慢。您正在绘制数十万个数据点。
data = Accumulate@RandomVariate[NormalDistribution[], 200000];
Manipulate[ListLinePlot[Take[data, n]], {n, 1, Length[data]}]
Manipulate
中,您允许Take
显示的数据量随意变化。请尝试每100个左右点增加numrows
,因此渲染的次数较少。ContinuousAction->False
选项(请参阅documentation)(我看到@Szabolcs的想法与我输入的内容相同。MaxPlotPoints
,而是尝试使用PerformanceGoal ->"Speed"
选项。 (见documentation)答案 2 :(得分:5)
我还注意到偶尔使用Mathematica渲染图形需要很长时间。实际上它必须是从Mathematica Graphics
表达式到一些其他表示的一些转换步骤,因为一旦渲染,调整大小(并因此重新渲染)图形要快得多。对于许多示例而言,版本6之前的图形渲染曾经更快(但也缺少6+以上的许多功能)。
关于你能做什么的一些想法:
使用MaxPlotPoints
的{{1}}选项在绘图前减少数据。如果它的下采样,它看起来可能没有区别。 ListLinePlot
选项应该选择缩减采样算法,但我找不到任何文档(任何人?)
在Method
中使用ContinuousAction -> False
阻止它在您拖动滑块时实时重新计算所有内容。
答案 3 :(得分:5)
此处的另一个想法是使用Ramer–Douglas–Peucker algorithm在绘图之前减少数据点的数量。这可能会更好地保留数据的形状。我不知道你是否还需要这个,所以我不会提供实现。