大规模PyPlot - 避免内存分配

2 投票
2 回答
1098 浏览
提问于 2025-04-16 15:47

我正在使用PyPlot(Python的matplotlib库)处理一个相当大的数据集(有60万个值,每个值占32位)。实际上,我想我可以简单地这样做:

import matplotlib.pyplot as plt
plt.plot([1,2,3,4], [1,4,9,16], 'ro')
plt.axis([0, 6, 0, 20])

我有两个数组,都是在内存中分配的。不过,我迟早会需要绘制包含几GB这些信息的文件。

我该如何避免将两个数组传递给plt.plot()呢?

不过我仍然需要一个完整的图表。所以我想,单纯用迭代器逐行传值是不行的。

2 个回答

0

你真的需要画出每一个点吗?其实用密度图也可以达到同样的效果,因为你有很多数据点可以用。你可以看看pylab里的hexbin或者numpy.histogram2d这两个工具。对于这么大的文件,你可能需要用numpy.memmap,或者像@samplebias说的那样,分批处理数据。

5

如果你要处理的是几GB的数据,建议你可以分批加载和绘制数据点,然后把每次绘制的图像叠加到之前的图像上。下面是一个简单的例子,里面有注释帮助理解:

import Image
import matplotlib.pyplot as plt
import numpy

N = 20
size = 4
x_data = y_data = range(N)

fig = plt.figure()

prev = None
for n in range(0, N, size):
    # clear figure
    plt.clf()

    # set axes background transparent for plots n > 0
    if n:
        fig.patch.set_alpha(0.0)
        axes = plt.axes()
        axes.patch.set_alpha(0.0)

    plt.axis([0, N, 0, N])

    # here you'd read the next x/y values from disk into memory and plot
    # them.  simulated by grabbing batches from the arrays.
    x = x_data[n:n+size]
    y = y_data[n:n+size]
    ax = plt.plot(x, y, 'ro')
    del x, y

    # render the points
    plt.draw()

    # now composite the current image over the previous image
    w, h = fig.canvas.get_width_height()
    buf = numpy.fromstring(fig.canvas.tostring_argb(), dtype=numpy.uint8)
    buf.shape = (w, h, 4)
    # roll alpha channel to create RGBA
    buf = numpy.roll(buf, 3, axis=2)
    w, h, _ = buf.shape
    img = Image.fromstring("RGBA", (w, h), buf.tostring())
    if prev:
        # overlay current plot on previous one
        prev.paste(img)
        del prev
    prev = img

# save the final image
prev.save('plot.png')

输出结果:

在这里输入图片描述

撰写回答