绘制大量数据

我们目前正在使用ZedGraph绘制一些数据的折线图。 输入数据来自任意大小的文件,因此,我们事先不知道最大数据点数是多少。 但是,通过打开文件并读取标题,我们可以找出文件中有多少数据点。

文件格式基本上是[时间(双精度),值(双精度)]。 但是,条目在时间轴上不一致。 在t = 0秒和t = 10秒之间可能没有任何点,但在t = 10秒和t = 11秒之间可能存在100K,依此类推。

例如,我们的测试数据集文件大约为2.6 GB,它有324M点。 我们想向用户展示整个图表,让她浏览图表。 然而,向ZedGraph加载324M点不仅是不可能的(我们使用的是32位机器),但也没用,因为屏幕上没有这么多点。

使用ZedGraph的FilteredPointListfunction似乎也是不可能的,因为这需要先加载整个数据,然后对该数据执行过滤。

因此,除非我们遗漏任何东西,否则我们唯一的解决方案似乎是 – 以某种方式对数据进行抽取,但是当我们不断努力时,我们遇到了很多问题:

1-我们如何抽取未及时到达的数据?

2-由于无法将整个数据加载到内存中,因此任何算法都需要在磁盘上运行,因此需要仔细设计。

3-我们如何处理放大和缩小,尤其是当数据在x轴上不均匀时。

如果数据是统一的,在初始加载图形时,我们可以通过文件中预定义的条目数量来Seek() ,并选择每N个其他样本并将其提供给ZedGraph。 但是,由于数据不统一,我们必须在选择要显示的样本时更加智能,并且我们无法提出任何不必读取整个文件的智能算法。

我道歉,因为这个问题没有严格的特异性,但我希望我可以解释我们问题的性质和范围。

我们在Windows 32位,.NET 4.0上。

我以前需要这个,这并不容易。 由于这个要求,我最终编写了自己的图形组件。 最后结果更好,因为我提供了我们需要的所有function。

基本上你需要获得数据范围(最小和最大可能/需要的索引值),细分为段(比如100段),然后通过某种算法确定每个段的值(平均值,中值等)。 )。 然后根据总结的100个元素进行绘图。 这比试图绘制数百万点要快得多:-)。

所以我所说的与你所说的相似。 你提到你不想绘制每个X元素,因为元素之间可能存在很长的时间(x轴上的索引值)。 我所说的是,对于每个细分细分,确定什么是最佳值,并将其作为数据点。 我的方法是基于索引值的,所以在你的0秒和10秒索引值之间没有数据的例子中,我仍然将数据点放在那里,它们之间只有相同的值。

重点是在绘制数据之前总结数据。 仔细考虑您的算法,有很多方法可以做到这一点,选择适合您的应用程序的算法。

您可能不会编写自己的图形组件而只是编写数据摘要算法。

我将通过两个步骤来解决这个问题:

  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.规范化数据并创建具有开,高,低,接近值的聚合数据条。 一个。 按时间b。 按记录计数c。 通过Diff之间的值

有关聚合非统一数据集的更多可能方法,您可能需要查看用于汇总金融市场中交易数据的不同方法。 当然,为了实时渲染速度,您需要创建已经聚合了这些数据的文件。

1-我们如何抽取未及时到达的数据?

注意 – 我假设您的加载器数据文件是文本格式。)

在类似的项目中,我不得不读取大小超过5GB的数据文件。 我可以解析它的唯一方法是将其读入RDBMS表。 我们之所以选择MySQL,是因为它将文本文件导入到数据表中简单易用。 (有趣的是 – 我在一台32位Windows机器上无法打开文本文件进行查看,但是MySQL没有问题。)另一个特权是MySQL 尖叫,快速尖叫

一旦数据在数据库中,我们就可以轻松地对其进行排序并将大量数据量化为单个释义查询(使用内置的SQL汇总函数,如SUM )。 MySQL甚至可以将其查询结果读回文本文件以用作加载器数据。

简而言之,消耗大量数据要求使用可以汇总数据的工具。 MySQL适合该法案(双关语……它是免费的)。

我发现这样做的一个相对简单的替代方法是执行以下操作:

  1. 在小点分组中迭代数据(一次说3到5个点 – 组越大,算法运行得越快,但聚合的准确性越低)。
  2. 计算小组的最小值和最大值。
  3. 从该组中删除所有不是最小值或最大值的点(即,每组只保留2个点并省略其余点)。
  4. 保持循环遍历数据(重复此过程)从开始到结束删除点,直到聚合数据集具有足够少的点数,可以在不阻塞PC的情况下绘制图表。

我过去曾使用过这种算法,将约1000万个点的数据集降低到~5K点的数量级,而图形没有任何明显的可见失真。

这里的想法是,在抛出点时,你会保留峰值和谷值,因此在最终图表中查看的“信号”不会“平均下降”(通常,如果平均,你会看到峰值和山谷变得不那么突出了)。

另一个优点是你总是在最终的图形上看到“真正的”数据点(它缺少一堆点,但是那些点实际上存在于原始数据集中,因此,如果你鼠标hover在某些东西上,你可以显示实际的x和y值,因为它们是真实的,而不是平均的)。

最后,这也有助于解决不具有一致x轴间距的问题(同样,您将拥有实际点而不是平均X轴位置)。

我不确定这种方法如何能够像你拥有的数百万个数据点一样有效,但它可能值得一试。