将 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
以尽量减少舍入误差。
假设我有一系列二维坐标(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
以尽量减少舍入误差。