【发布时间】:2018-03-02 18:28:39
【问题描述】:
我想做一个大型数据集的二维直方图。如果我一次打开所有数据,我会收到 MemoryError 消息。因此,我将数据细分为可以单独加载的较小块。问题是我可以为每个块制作一个 2D 直方图,但不能一次为整个数据集制作一个 2D 直方图,因为我不能一次全部加载。
让我们看一个玩具示例。在这里想象 x 和 y 是来自我的一个块的数据。在此示例中,“块”由一百万个数据点组成:
import numpy as np
import matplotlib.pyplot as plt
x=np.random.normal(-1,1,1000000)
y=np.random.normal(-1,1,1000000)
#CLASSIC WAY TO MAKE A 2D HISTOGRAM
plt.hist2d(x,y,bins=100)
plt.savefig("histo1.png",dpi=800)
plt.close()
#ALTERNATIVE WAY TO MAKE A 2D HISTOGRAM
arr, xedges, yedges=np.histogram2d(x,y,bins=100)
frame=[xedges[0], xedges[-1], yedges[0], yedges[-1]]
plt.imshow(np.rot90(arr), interpolation="none", extent=frame)
plt.savefig("histo2.png",dpi=800)
plt.close()
所以在这里我展示了两种不同的方法来制作完全相同的图像:经典方法是使用 matplotlib.pyplot.hist2d() 直接从数据中绘制直方图,另一种方法是首先从数据中创建密度矩阵(使用 numpy.histogram2d())然后使用 matplotlib.pyplot.imshow() 绘制它。
所有这些都可以正常工作,并且两种方法都会产生完全相同的图像。但现在我想为整个数据集制作直方图。我不能用经典的方式来做,因为加载 x=x_data_chunk1+x_data_chunk2+... 和 y=y_data_chunk1+y_data_chunk2+... 由于 RAM 内存过载是不可能的。但理论上,替代方法应该有效;我可以加载第一个块并提取 x 和 y,然后使用 numpy.histogram2d() 对其进行密度矩阵,存储它,删除 x 和 y 的数据并对下一个块执行相同的操作。最后,我们将为每个块创建一个密度矩阵,而无需同时加载其中的任何两个。密度矩阵不是问题,因为它们只是计算每个单元格中数据点数量的网格(它们占用的数据显然比实际数据少得多)。最后,我们将所有密度矩阵添加到一个中,并使用 matplotlib.pyplot.imshow() 绘制最终排列。
理论上这应该可行。所以我首先尝试了一个玩具示例,它使用两个数据块 (x1,y1) 和 (x2,y2) 来查看如果可以同时加载数据(只是看看它是否和以前一样在两种方式下都是相同的图像,即使在真实情况下由于MemoryError,用经典方式是不可能的)。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
#CHUNK OF DATA 1
x1=np.random.normal(-1,1,1000000)
y1=np.random.normal(-1,1,1000000)
#CHUNK OF DATA 2
x2=np.random.normal(-1,1,1000000)
y2=np.random.normal(-1,1,1000000)
#CLASSIC WAY
x=x1+x2
y=y1+y2
plt.hist2d(x,y,bins=100)
plt.savefig("histo1.png",dpi=800)
plt.close()
#ALTERNATIVE WAY
arr1, xedges1, yedges1=np.histogram2d(x1,y1,bins=100)
arr2, xedges2, yedges2=np.histogram2d(x2,y2,bins=100)
arr=arr1+arr2
frame=[min([xedges1[0],xedges2[0]]), max([xedges1[-1],xedges2[-1]]), min([yedges1[0],yedges2[0]]), max([yedges1[-1],yedges2[-1]])]
plt.imshow(np.rot90(arr), interpolation="none", extent=frame)
plt.savefig("histo2.png",dpi=800)
plt.close()
这样做我得到两个完全不同的图像。为什么会这样? 标题是我试图在这里解决的一个更一般的问题,但我真的很想知道如何解决这种特殊情况。
这里真正的问题是 如何制作 2D 直方图,将不同数据块的密度矩阵相加,并获得与对整个数据集使用 matplotlib.pyplot.hist2d() 相同的结果?
这个问题的标题没有足够的空间,我无法想象它的更简洁的版本,所以最后我决定提出一个更一般的问题并解释我的特殊情况。不便之处请见谅。
【问题讨论】:
-
为什么要添加
x1和x2- 你不想连接它们吗?即x = np.concatenate([x1,x2])。y也一样。如果这解决了问题,请告诉我,我可以制定答案。
标签: python numpy matplotlib