大规模PyPlot - 避免内存分配
我正在使用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')
输出结果: