[英]Vectorize calling numpy function on third dimension of array
I have a 3D numpy array data
where dimensions a
and b
represent the resolution of an image and c
is the image/frame number.我有一个 3D numpy 数组data
,其中尺寸a
和b
代表图像的分辨率, c
是图像/帧号。 I want to call np.histogram
on each pixel ( a
and b
combination) across the c
dimension, with an output array of dimension (a, b, BINS)
.我想在np.histogram
上的每个像素( a
和b
组合)上调用c
,并使用维度为(a, b, BINS)
BINS) 的 output 数组。 I've accomplished this task with a nested loop, but how can I vectorize this operation?我已经用一个嵌套循环完成了这个任务,但是我怎样才能向量化这个操作呢?
hists = np.zeros((a, b, BINS))
for row in range(a):
for column in range(b):
hists[row, column, :] = np.histogram(data[row, column, :], bins=BINS)[0]
I am confident that the solution is trivial, nonetheless all help is appreciated:)我相信该解决方案是微不足道的,但感谢所有帮助:)
np.histogram
computes over the flattened array. np.histogram
在展平数组上进行计算。 However, you could use np.apply_along_axis
.但是,您可以使用np.apply_along_axis
。
np.apply_along_axis(lambda a: np.histogram(a, bins=BINS)[0], 2, data)
This is interesting problem.这是一个有趣的问题。
It should be the main habit in asking questions on SO.这应该是在 SO 上提问的主要习惯。
a, b, c = 2, 3, 4
data = np.random.randint(10, size=(a, b, c))
hists = np.zeros((a, b, c), dtype=int)
for row in range(a):
for column in range(b):
hists[row, column, :] = np.histogram(data[row, column, :], bins=c)[0]
data
>>> array([[[6, 4, 3, 3],
[7, 3, 8, 0],
[1, 5, 8, 0]],
[[5, 5, 7, 8],
[3, 2, 7, 8],
[6, 8, 8, 0]]])
hists
>>> array([[[2, 1, 0, 1],
[1, 1, 0, 2],
[2, 0, 1, 1]],
[[2, 0, 1, 1],
[2, 0, 0, 2],
[1, 0, 0, 3]]])
You can eliminate one loop and simplify it:您可以消除一个循环并简化它:
new_data = data.reshape(a*b, c)
new_hists = np.zeros((a*b, c), dtype=int)
for row in range(a*b):
new_hists[row, :] = np.histogram(new_data[row, :], bins=c)[0]
new_hists
>>> array([[2, 1, 0, 1],
[1, 1, 0, 2],
[2, 0, 1, 1],
[2, 0, 1, 1],
[2, 0, 0, 2],
[1, 0, 0, 3]])
new_data
>>> array([[6, 4, 3, 3],
[7, 3, 8, 0],
[1, 5, 8, 0],
[5, 5, 7, 8],
[3, 2, 7, 8],
[6, 8, 8, 0]])
In general, you can't vectorise something like that is being done in loop:通常,您不能对循环中正在执行的类似操作进行矢量化:
for row in array:
some_operation(row)
Except the cases you can call another vectorised operation on flattened array and then move it back to the initial shape:除了可以在展平数组上调用另一个矢量化操作然后将其移回初始形状的情况外:
arr = array.ravel()
another_operation(arr)
out = arr.reshape(array.shape)
It looks you're fortunate with np.histogram
because I'm pretty sure similar things have been done before .看起来你对np.histogram
很幸运,因为我很确定以前做过类似的事情。
new_data = data.reshape(a*b, c)
m, M = new_data.min(axis=1), new_data.max(axis=1)
bins = (c * (new_data - m[:, None]) // (M-m)[:, None])
out = np.zeros((a*b, c+1), dtype=int)
advanced_indexing = np.repeat(np.arange(a*b), c), bins.ravel()
np.add.at(out, advanced_indexing, 1)
out.reshape((a, b, -1))
>>> array([[[2, 1, 0, 0, 1],
[1, 1, 0, 1, 1],
[2, 0, 1, 0, 1]],
[[2, 0, 1, 0, 1],
[2, 0, 0, 1, 1],
[1, 0, 0, 1, 2]]])
Note that it adds an extra bin in each histogram and puts max values in it but I hope it's not hard to fix if you need.请注意,它在每个直方图中添加了一个额外的 bin 并将最大值放入其中,但我希望如果您需要修复它并不难。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.