查找 numpy 数组中填充最多的"slice"



我有一个形状为[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)

最后一个解决方案所花费的时间是其他两个解决方案的一半。我们可以提供这种技巧,因为掩码实际上是01值的矩阵。如果存在其他值,它将不起作用。


进一步评论:

如果foo的类型是bool(掩码应该是(,那么所有这些方法似乎都需要完全相同的时间(在误差范围内(,这表明,也许在幕后,布尔值的count_nonzerosum非常相似?不过,我不知道,如果能有一些见解就好了。

我想这就是您所需要的:

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)]

尽管我预计丹卡尔和麦克索尼的回答都会更快。

最新更新