【问题标题】:Memory error when dealing with huge data处理大数据时出现内存错误
【发布时间】:2011-12-08 19:33:14
【问题描述】:

我想使用 matplotlib 绘制直方图。但是,由于我发送给 hist() 函数的数据量很大(包含大约 100,000 个数字的列表),绘制两个图形时会出现错误。但它进展顺利,同时只绘制了两个情节中的任何一个。谁能帮我处理这个问题?提前致谢。

这是显示错误的简化代码:

f_120 = plt.figure(1)
plt.hist(taccept_list, bins=6000000, normed = True, histtype ="step", cumulative = True, color = 'b', label = 'accepted answer')
plt.hist(tfirst_list, bins=6000000, normed = True, histtype ="step", cumulative = True, color = 'g',label = 'first answer')
plt.axvline(x = 30, ymin = 0, ymax = 1, color = 'r', linestyle = '--', label = '30 min')
plt.axvline(x = 60, ymin = 0, ymax = 1, color = 'c', linestyle = '--', label = '1 hour')
plt.legend()

plt.ylabel('Percentage of answered questions')
plt.xlabel('Minutes elapsed after questions are posted')
plt.title('Cumulative histogram: time elapsed \n before questions receive answer (first 2 hrs)')
plt.ylim(0,1)
plt.xlim(0,120)
f_120.show()
f_120.savefig('7month_0_120.png', format = 'png' )
plt.close()

f_2640 = plt.figure(2)
plt.hist(taccept_list, bins=6000000, normed = True, histtype ="step", cumulative = True, color = 'b', label = 'accepted answer')
plt.hist(tfirst_list, bins=6000000, normed = True, histtype ="step", cumulative = True, color = 'g',label = 'first answer')
plt.axvline(x = 240, ymin = 0, ymax = 1, color = 'r', linestyle = '--', label = '4 hours')
plt.axvline(x = 1440, ymin = 0, ymax = 1, color = 'c', linestyle = '--', label = '1 day')
plt.legend(loc= 4)

plt.ylabel('Percentage of answered questions')
plt.xlabel('Minutes elapsed after questions are posted')
plt.title('Cumulative histogram: time elapsed \n before questions receive answer (first 48)')
plt.ylim(0,1)
plt.xlim(0,2640)
f_2640.show()
f_2640.savefig('7month_0_2640.png', format = 'png' )

以下是错误详情:

plt.hist(tfirst_list, bins=6000000, normed = True, histt​​ype ="step", 累积 = True, color = 'g',label = 'first answer')

文件“C:\software\Python26\lib\site-packages\matplotlib\pyplot.py”,第 2160 行,在 hist ret = ax.hist(x, bins, range, normed, weights,cumulative, bottom, histt​​ype, align,orientation, rwidth, log, color, label, **kwargs)

文件“C:\software\Python26\lib\site-packages\matplotlib\axes.py”,第 7775 行,在 hist 关闭=假,边缘颜色=c,填充=假))

文件“C:\software\Python26\lib\site-packages\matplotlib\axes.py”,第 6384 行,填充 对于 self._get_patches_for_fill(*args, **kwargs) 中的 poly:

文件“C:\software\Python26\lib\site-packages\matplotlib\axes.py”,第 317 行,在 _grab_next_args 对于 self._plot_args(remaining, kwargs) 中的 seg:

文件“C:\software\Python26\lib\site-packages\matplotlib\axes.py”,第 304 行,在 _plot_args seg = func(x[:,j%ncx], y[:,j%ncy], kw, kwargs)

文件“C:\software\Python26\lib\site-packages\matplotlib\axes.py”,第 263 行,在 _makefill (x[:,np.newaxis],y[:,np.newaxis])),

文件“C:\software\Python26\lib\site-packages\numpy\core\shape_base.py”,第 270 行,在 hstack 中 return _nx.concatenate(map(atleast_1d,tup),1)

内存错误

【问题讨论】:

  • 请发布回溯。嗯,你为什么要绘制两次相同的数字?
  • 你真的需要 600 万个垃圾箱吗?我不明白为什么它无论如何都不应该工作,但是对于这种情况,matplotlib 可能没有非常有效地实现。即使是在 A4 纸上的高质量打印,也只有一万列左右。你的情节分辨率是多少?
  • @rlibby 对不起,我是 matplotlib 的新手,我不知道如何获得我的情节的分辨率。它只是完美地显示了任何一个情节,但在将它们绘制在一起时会崩溃。
  • @Avaris 实际上我想使用相同的数据来显示同一直方图的两个不同范围。并且在运行此脚本时,第一个数字被成功保存,而在处理第二个数字时,显示“内存错误”并且我再次运行以获取回溯
  • @AnneS,如果您不需要查看该图,您可以在不调用show() 的情况下保存它。而且你不需要再次绘图来调整参数xlimylim等...只需调整,保存,再次调整,再次保存,...

标签: python matplotlib


【解决方案1】:

正如其他人所指出的,600 万个垃圾箱听起来并不是很有用。但一个简单的事情是重用相同的图形:因为唯一改变的绘图元素是直方图以外的东西,尝试这样的事情:

vline1 = plt.axvline(...)
vline2 = plt.axvline(...)
lgd = legend()

在 savefig 之后不要关闭图形并绘制新的直方图,而是重复使用它,更改需要更改的内容:

# change vline1 and vline2 positions and labels
vline1.set_data([240,240],[0,1])
vline1.set_label('new label')
vline2.set_data(...)
vline2.set_label(...)
# remove old legend, replace with new
lgd.remove()
lgd = plt.legend(loc=4)
plt.xlabel('new xlabel')
# etc

最后用新的文件名再次调用 savefig。

【讨论】:

    【解决方案2】:

    您绘制了 600 万个 bin,然后放大(大概)其中的一小部分。每个图有两条线,即 1200 万个数据点,一旦您尝试在下一个图中再绘制 1200 万个数据点,我并不感到惊讶 matplotlib 崩溃。我非常怀疑您是否真的需要 600 万个 bin,所以让我们尝试将您的直方图缩小到更易于管理的大小!

    假设您的数据跨越了您希望查看的 44 或 48 小时。然后使用 600 万个 bin,这意味着您的数据具有 30 毫秒的分辨率。考虑到您显示的分钟分辨率,这似乎不合理。或者,您的分辨率为秒,因此 600 万个 bin 意味着您的数据跨越 70 天,但您只查看其中的两个。

    假设您对以秒或分钟为单位的两天数据感兴趣。

    虽然您将 bin 指定为多个 bin,但您也可以指定一个值范围。因此,对于您的第一个图表,您可以说

    plt.hist(taccept_list, bins=range(120), normed = True, histtype ="step", cumulative = True, color = 'b', label = 'accepted answer')
    plt.hist(tfirst_list, bins=range(120), normed = True, histtype ="step", cumulative = True, color = 'g',label = 'first answer')
    

    在前 120 分钟内为您提供几分钟的解决方案。直方图将忽略任何高于 120 的值,这很好,因为无论如何您都不会在绘图中显示它。

    在几秒钟内解决的替代方法可能是:

    numpy.linspace(0,120,7200)
    

    现在,直方图中的点数更加合理,可能更符合您正在查看/显示的数据。

    【讨论】:

      猜你喜欢
      • 2018-09-15
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-11
      • 2022-06-16
      • 1970-01-01
      相关资源
      最近更新 更多