有没有比遍历numpy数组更快的方法?

时间:2020-09-22 17:10:22

标签: python python-3.x numpy loops vectorization

如果我有两个numpy值数组;如何快速制作第三个数组,使我获得前两个数组中相同的两个值的次数?

例如:

x = np.round(np.random.random(2500),2)
xIndex = np.linspace(0, 1, 100)

y = np.round(np.random.random(2500)*10,2)
yIndex = np.linspace(0, 10, 1000)

z = np.zeros((100,1000))

现在,我正在执行以下循环(速度太慢了):

for m in x:
    for n in y:
        q = np.where(xIndex == m)[0][0]
        l = np.where(yIndex == n)[0][0]
        z[q][l] += 1

然后,我可以绘制xIndex,yIndex和z的等高线图(或热图,等等)。但是我知道我并没有采取“ Python式”的方式来解决此问题,而且在任何接近合理的时间范围内,我都无法运行我拥有的数亿个数据点。

如何正确执行此操作?感谢您的阅读!

1 个答案:

答案 0 :(得分:4)

您可以大幅截断代码。

首先,由于分箱时使用的是线性比例,因此可以完全消除显式数组xIndexyIndex。您可以将精确的索引表示为z

xi = np.round(np.random.random(2500) * 100).astype(int)
yi = np.round(np.random.random(2500) * 1000).astype(int)

第二,您不需要循环。普通+运算符(也称为np.add)的问题在于它已被缓冲。这样做的结果是,对于相同索引的多个事件,您将得不到正确的计数。幸运的是,ufunc具有一个at方法来处理该问题,而add是一个ufunc。

第三,最后,广播允许您指定如何为花式索引对数组进行网格划分:

np.add.at(z, (xi[:, None], yi), 1)

如果要构建2D直方图,则无需四舍五入原始数据。您可以只对索引取整:

x = np.random.random(2500)
y = np.random.random(2500) * 10

z = np.zeros((100,1000))
np.add.at(z, (np.round(100 * x).astype(int), np.round(100 * y).astype(int)), 1)