我有一个形状为[x_len,y_len,z_len]的numpy掩码。我希望找到z,使得np.count_nonzero(mask[:,:,z](最大化。
我天真的解决方案:
best_z = -1
best_score = -1
for z in range(mask.shape[2]):
n_nonzero = np.count_nonzero(mask[:,:,z])
if n_nonzero > best_score:
best_score = n_nonzero
best_z = z
但我正在寻找更快和/或更漂亮的东西。
np.argmax(np.count_nonzero(foo, axis=(0, 1)))
产生存在最大非零元素的CCD_ 2的z索引。
为了比较这个解决方案,与@mcsoini的解决方案和另一个新的解决方案:
foo = np.random.randint(0, 2, size=(100, 100, 200))
# this solution
i> %timeit np.argmax(np.count_nonzero(foo, axis=(0, 1)))
o> 1.58 ms ± 43.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# @mcsoini's solution
i> %timeit np.argmax(np.count_nonzero(foo.reshape(-1, foo.shape[-1]), axis=0))
o> 1.64 ms ± 18.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# a trick solution
i> %timeit np.argmax(np.sum(foo, axis = (0, 1)))
o> 709 µs ± 4.87 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
最后一个解决方案所花费的时间是其他两个解决方案的一半。我们可以提供这种技巧,因为掩码实际上是0
和1
值的矩阵。如果存在其他值,它将不起作用。
进一步评论:
如果foo
的类型是bool
(掩码应该是(,那么所有这些方法似乎都需要完全相同的时间(在误差范围内(,这表明,也许在幕后,布尔值的count_nonzero
与sum
非常相似?不过,我不知道,如果能有一些见解就好了。
我想这就是您所需要的:
best_z = np.argmax(np.count_nonzero(mask, axis=-1))
编辑:出现错误,轴应为(0, 1)
:
best_z = np.argmax(np.count_nonzero(mask, axis=(0, 1))
感谢mcsoini注意到
您正在沿着z轴查找索引,该索引对应于具有最多非零元素的数组切片。使用示例数据
np.random.seed(3)
mask = np.random.randn(2, 3, 4)
mask = np.where(mask < 0, 0, mask)
print(mask)
[[[1.78862847 0.43650985 0.09649747 0. ]
[0. 0. 0. 0. ]
[0. 0. 0. 0.88462238]]
[[0.88131804 1.70957306 0.05003364 0. ]
[0. 0. 0.98236743 0. ]
[0. 0. 1.48614836 0.23671627]]]
我们可以首先重塑阵列CCD_ 12以便将维度0和1减小到单个维度。然后,我们沿着这个新的第一维p.count_nonzero(..., axis=0)
计算非零的数量,最后我们可以找到沿着z的索引,其中这些计数是最大的(np.argmax
(:
np.argmax(np.count_nonzero(mask.reshape(-1, mask.shape[-1]), axis=0))
结果:2
我想到了这个:
unique, counts = np.unique(np.where(mask)[2], return_counts=True)
best_z = unique[np.argmax(counts)]
尽管我预计丹卡尔和麦克索尼的回答都会更快。