将 2d 数组排序到 bin 中并在每个 bin 中添加权重

Sorting 2d array into bins and add weights in each bin

假设我有一系列二维坐标(x, y),每个坐标对应一个权重。在我将它们排列成箱子(即一个小方形区域)后,我想找到落入每个箱子的重量总和。我使用 np.digitize 来查找我的数据属于哪个 bin,然后我使用循环在每个 bin 中添加权重。我的代码是这样的:

import numpy as np

x = np.random.uniform(low=0.0, high=10.0, size=5000) #x variable
y = np.random.uniform(low=0.0, high=10.0, size=5000) #y variable
w = np.random.uniform(low=0.0, high=10.0, size=5000) #weight at each (x,y)

binx = np.arange(0, 10, 1)
biny = np.arange(0, 10, 1)

indx = np.digitize(x, binx)
indy = np.digitize(y, biny)

#initialise empty list
weight = [[0] * len(binx) for _ in range(len(biny))]

for n in range(0, len(x)):
    for i in range(0, len(binx)):
        for j in range(0, len(biny)):
            if indx[n] == binx[i] and indy[n] == biny[j]:
                weight[i][j] =+ w[n]

但是输出的第一行weight是空的,没有意义。为什么会这样?有没有更有效的方法来做我想做的事?

编辑:我在下面有一个很好的答案(我接受了一个),但我想知道如果我将垃圾桶作为浮点数,它是如何工作的?--> 查看编辑后的答案

您可以通过简单的索引来做到这一点。先获取各个方向的bin号。对于均匀间隔的垃圾箱,您不需要 np.digitize

xbin = (x // 1).astype(int)
ybin = (y // 1).astype(int)

现在制作输出网格:

grid = np.zeros_like(w, shape=(xbin.max() + 1, ybin.max() + 1))

现在,使用重复 bin 正确完成加法的技巧是在无缓冲模式下进行。像 np.add have a method at 这样的 Ufunc 就是为了这个目的:

np.add.at(grid, (xbin, ybin), w)

附录

这种方法对于任何偶数大小的容器都是完全通用的。假设你有

x = np.random.uniform(low=-10.0, high=10.0, size=5000)
y = np.random.uniform(low=-7.0, high=12.0, size=5000)

xstep = 0.375
ystep = 0.567

假设您想计算从 x.min()y.min() 开始的 bin。您可以改用固定偏移量,甚至将 np.clip 应用于越界索引,但这将留作 reader.

的练习。
xbin = ((x - x.min()) // xstep).astype(int)
ybin = ((y - y.min()) // ystep).astype(int)

其他一切都应该与原始简化案例相同。

绘制直方图时,您的 x 轴和 y 轴将是

xax = np.linspace(x.min(), x.min() + xstep * xbin.max(), xbin.max() + 1) + 0.5 * xstep
yax = np.linspace(y.min(), y.min() + ystep * ybin.max(), ybin.max() + 1) + 0.5 * ystep

我在这里避免使用 np.arange 以尽量减少舍入误差。