Python/Numpy:对每一行执行一个np.all相当于不同的列

Python/Numpy: Perform an np.all equivalent to different columns for each row

我正在寻找一种矢量化和内存高效的解决方案,以将 np.all 的等价物应用于 3-d numpy 数组的每一行,其中每一行都有一组不同的列 np.all 在一起。对于每一行,要应用 np.all 的列由第二个数组标识。

要执行操作的数组是 dataArr,一个形状为 (5, 3, 5) 的 3 维 numpy 布尔数组。

dataArr = np.array([  
                    [[1, 1, 1, 0, 1], [0, 0, 0, 0, 0], [1, 1, 1, 1, 0]],
                    [[0, 0, 0, 0, 0], [1, 0, 1, 1, 1], [1, 0, 1, 1, 1]],
                    [[1, 0, 1, 1, 1], [1, 1, 1, 0, 1], [0, 0, 0, 0, 0]],
                    [[1, 1, 1, 0, 1], [0, 0, 0, 0, 0], [1, 0, 1, 1, 1]], 
                    [[0, 0, 0, 0, 0], [1, 0, 1, 0, 1], [0, 1, 1, 1, 0]]
])

包含数据的数组标识要包含在 dataArr 中每一行的 np.all 操作(或等效)中的数组称为 relCols,一个二维 numpy 布尔值具有与 dataArr 相同行数和列数的形状 (5, 3) 数组。每行中的值表示 dataArr 对应行中的哪些列应用 np.all

relCols = np.array([
                    [1, 0, 1],      #apply equivalent of np.all to dataArr[0,(0,2)]
                    [0, 1, 1],      #apply equivalent of np.all to dataArr[1,(1,2)]
                    [1, 1, 0],      #apply equivalent of np.all to dataArr[2,(0,1)]
                    [1, 0, 1],      #apply equivalent of np.all to dataArr[3,(0,2)]
                    [0, 1, 1]       #apply equivalent of np.all to dataArr[4,(1,2)]
]) 

这是我的应用程序的简化版本,其中 dataArr 大得多,因此如果可能的话,我正在寻找完全矢量化的方法。

我目前所做的是对dataArr 中不相关的列使用np.ones 并使用np.all(dataArr, axis=1)。虽然这有效,但它增加了显着的不必要的内存开销,这正是我试图减轻的。

想要的结果:

result = np.array([  
                    [1, 1, 1, 0, 0],
                    [1, 0, 1, 1, 1],
                    [1, 0, 1, 0, 1],
                    [1, 0, 1, 0, 1],
                    [0, 0, 1, 0, 0]
])

非常感谢任何帮助。

下面是一些示例代码,显示了我原来的方法的效果。 dataArr 已调整大小以模仿我可能遇到的情况。 np.ones 以下未明确使用,但包含零的不相关列已替换为一。

def original():

    dataArr = np.array([  
                        [[1, 1, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 0, 0, 1, 0, 1, 1]],
                        [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 1, 0, 1, 1, 1, 0, 1, 1]],
                        [[1, 0, 1, 1, 1, 1, 0, 1, 1, 0], [1, 1, 1, 0, 1, 1, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
                        [[1, 1, 1, 0, 1, 0, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 1, 0, 1, 0, 1, 1, 1]], 
                        [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0, 1, 1, 0, 1], [0, 1, 1, 0, 1, 0, 1, 0, 1, 1]]
    ], dtype=bool)

    dataArr = np.repeat(dataArr,200000, axis=0); 
    dataArr = np.repeat(dataArr,100, axis=2);   #resulting shape = (1000000, 3, 1000)

    dataReduced = np.all(dataArr, axis=1)

尝试使用掩码数组。 documentation -

中有更多详细信息
  1. 首先用 np.ones_like 创建一个掩码,然后通过向其添加一个轴来减去广播的 relCols
  2. 接下来,从 dataArr
  3. 创建一个掩码数组
  4. 在 axis=1 上使用 np.all 计算非屏蔽值的操作并忽略屏蔽值。
mask = np.ones_like(dataArr) - relCols[...,None]
maskedArr = np.ma.MaskedArray(dataArr, mask)
np.all(maskedArr, axis=1).astype(int).data
array([[1, 1, 1, 0, 0],
       [1, 0, 1, 1, 1],
       [1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1],
       [0, 0, 1, 0, 0]])