基于参考n维数组对n维数组进行操作的最有效方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于参考n维数组对n维数组进行操作的最有效方法相关的知识,希望对你有一定的参考价值。

我有两个相同形状的Numpy数组:dat_araref_ara

我想对op_funcaxis = -1执行操作dat_ara,但是我只想对每个数组中选定的值切片进行操作,当超过阈值thres时指定切片通过参考数组ref_ara

为了说明,在简单的情况下,数组只是2维,我有:

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

[我们看到在thresaxis=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

我已经尝试扩展两个数组的维,以将它们关联以进行计算,即:

assos_ara = np.append(np.expand_dims(dat_ara, axis=-1), np.expand_dims(ref_ara, axis=-1), axis=-1)

但是同样,numpy.apply_along_axis要求输入函数只能在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.averagenp.sum),这很容易,但是对于更复杂的操作可能会更困难。

自numpy 1.17.0起,np.sum具有np.divide关键字:

np.divide

以上是关于基于参考n维数组对n维数组进行操作的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章

看图学NumPy:掌握n维数组基础知识点,看这一篇就够了

嵌套循环:置换由向量表示的 n 维数组

如何将M维数组转换为N维数组?

怎样在MATLAB中创建空的N维数组?

如何为数组的'n'个维循环?

Python / numpy:对数组的n个元素求和的最有效方法,以便每个输出元素是前n个输入元素的总和?