使用掩码、np.where函数缩减数组并进行计算

3

假设我有以下数组(实际上它是一个KxNxM掩码数组,其中存储了1514764800个字段,例如:np.ma.array(data, mask=mask, dtype=np.float32)):

import numpy as np
data = np.random.random((3,4,4))
mask = np.zeros((3,4,4), dtype=bool)
mask[1,2,2] = 1
mask[2,2,2] = 1
mask[2,1,3] = 1
mask[:,2,0] = 1

使用掩码,我可以轻松地将大数据集减少到有效的数据:

newdata = data[mask]
newdata
array([ 0.91336042,  0.78399595,  0.9466537 ,  0.75347407,  0.8213428 ,
    0.13172648])

为了知道它们所在的行/列和第三维,我可以使用:
pos = np.where(mask)
pos
(array([0, 1, 1, 2, 2, 2], dtype=int64),
array([2, 2, 2, 1, 2, 2], dtype=int64),
array([0, 0, 2, 3, 0, 2], dtype=int64))

这些信息(“newdata”和“pos”)可以保存,这样我就可以节省大量内存和存储空间。但是,我该如何计算例如在data [:,2,2]的所有字段的平均值(在原始数据中)?在我的情况下,newdata有约5300000个条目。


虽然有时使用起来有些棘手,但你尝试过掩码数组了吗?(我猜你的意思是要计算排除掩码值后的平均值)。 - Iguananaut
目标是将大数组减少到有效的数组,保留它们的位置。我的数据存储在掩码数组中。然而,我想将大数组(np.float32,约1514764800个元素)减少到仅考虑有效值的可处理数据集。 - HyperCube
这基本上就是遮罩数组的要点。您正在使用普通的 ndarray 并直接应用布尔遮罩,但是在较新版本的 Numpy 中,numpy.ma 模块具有专门用于此目的的特殊 masked_array 类型。 - Iguananaut
好的,我现在明白你的意思了。因为你的例子中没有指定,所以不太清楚。 - Iguananaut
2
你可以尝试将其转换为稀疏矩阵? - M4rtini
显示剩余3条评论
2个回答

2

以前从未听说过稀疏矩阵!我会去了解一下。然而,它们似乎只能处理二维矩阵。在我的情况下,同一行/列有多个值。 - HyperCube

0

对于你提到的特定情况,可以尝试以下方法:

In [33]: newmask = pos[0][np.logical_and(pos[1] == 2, pos[2] == 2)]

In [34]: data[:,2,2][newmask]
Out[34]: array([ 0.83677029,  0.34970232])

这种方法可以推广到适用于任意的切片,但是我现在没有时间提供完整的解决方案。我不禁想知道这是否已经内置在Numpy中。


考虑到数据(旧的大数组)之后应该避免使用,这有帮助吗? - HyperCube
1
我明白了——一旦你应用了所需的掩码,你想要完全丢弃掩码数据。在这种情况下,我同意@Yariv的答案使用稀疏矩阵。顺便说一句,如果你想看一个广泛使用稀疏矩阵的项目,QuTiP源代码中有很多好的例子(虽然不是针对3D数组)。 - Iguananaut
感谢您的努力! - HyperCube

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接