我有两个形状相同的numpy数组:dat_ara
和ref_ara
。
我想在op_func
的{{1}}上执行操作axis = -1
,但是我只想对每个数组中选定的值切片进行操作,当阈值dat_ara
被参考数组thres
越过。
为说明起见,在简单的数组只有2维的情况下,我有:
ref_ara
我们看到thres = 4
op_func = np.average
ref_ara = array([[1, 2, 1, 4, 3, 5, 1, 5, 2, 5],
[1, 2, 2, 1, 1, 1, 2, 7, 5, 8],
[2, 3, 2, 5, 1, 6, 5, 2, 7, 3]])
dat_ara = array([[1, 0, 0, 1, 1, 1, 1, 0, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 0, 1, 0],
[1, 0, 1, 1, 1, 1, 0, 1, 1, 1]])
的{{1}}中第一,第二和第三数组的第五,第七和第三索引中违反了thres
。因此,我希望得到的结果是
axis=0
此问题很困难,因为它需要引用ref_ara
。如果不是这种情况,我可以简单地使用out_ara = array([op_func(array([1, 0, 0, 1, 1, 1]),
op_func(array([1, 1, 1, 1, 1, 1, 1, 0]),
op_func(array([1, 0, 1, 1])])
。
我尝试扩展两个数组的尺寸以将它们关联以进行计算,即:
ref_ara
但是同样,numpy.apply_along_axis
要求输入函数只能在1维数组上运行,因此我仍然无法使用该函数。
我知道的另一种方法是明智地遍历数组索引,但是,由于两个数组的尺寸不断变化,这是一件棘手的事情,而且,它的计算效率也不高。
我想尽可能地使用矢量化函数来辅助此过程。最有效的解决方法是什么?
答案 0 :(得分:1)
这是带掩码数组的一个很好的用例,因为它们使您可以对部分数据执行常规的numpy操作。
让我们假设每一行至少包含一个大于阈值的值。您可以将断点的索引计算为
breaks = np.argmax(ref_ara > thres, axis=-1) # 5, 7, 3
然后可以使用answer到我先前链接的question来创建掩码。掩码通常是处理numpy中不规则形状数据的最佳方法。
mask = np.arange(ref_ara.shape[-1]) <= breaks.reshape(*breaks.shape, 1)
在这里,我们不需要对arange
做任何幻想,因为它沿最后一个维度。如果不是这种情况,您可能想要在范围将要到达的中断形状中插入1,并在范围形状的尾部也添加一个。
现在,掩码数组和ufunc解决方案略有不同。掩码数组版本更通用,因此它是第一个:
data = np.ma.array(data_ara, mask=~mask)
屏蔽数组从普通布尔索引的作用向后解释掩码,因此我们将掩码反转。另外,您可以使用>
而不是<=
计算掩码。现在的计算很简单:
out_ara = np.ma.average(data, axis=-1).data
一种不太通用的替代方法是将您的操作分解为ufunc,并使用它们提供的屏蔽。对于np.average
和np.sum
来说,这很容易,但对于更复杂的操作而言可能会更困难。
从numpy 1.17.0开始,np.sum
具有一个where
关键字:
out_ara = np.sum(dat_ara, where=mask, axis=-1) / breaks