我正在使用掩码对 numpy 数组进行切片,但输出被展平了。如何保留列数?

I'm using a mask to slice a numpy array, but the output is flattened. How do I retain the number of columns?

这是我目前的情况:

arr = np.round(np.random.uniform(0,1,size = (10,10)),decimals = 0)
print(arr)
arr2 = np.cumsum(arr,axis=0)
print(arr2)
mask = np.where((arr == 1)&(arr2<=3),1,0)
print(mask)
population = np.round(np.random.uniform(0,5,size=(10,10)),decimals=0)
print(population)
maskedPop = population[mask==1]
print(maskedPop)

这会输出一个展平的数组,有什么方法可以保留这 10 列吗?所以输出将是 3x10?

看起来 maks 每列产生相同数量的非零行。所以你可能会屏蔽(直接使用布尔数组)和 reshape:

population[(arr == 1)&(arr2<=3)].reshape(3,-1)

array([[3., 2., 5., 0., 4., 2., 0., 4., 5., 1.],
       [4., 3., 5., 3., 4., 1., 1., 4., 5., 4.],
       [3., 3., 4., 3., 4., 2., 4., 4., 1., 5.]])

请注意,输出是扁平化的,因为 numpy 不知道结果应该是二维齐次数组。如果 mask.sum(0) 每列产生不同的值,您将无法重建为 ndarray,因此 numpy 不会为您进行猜测。

您的代码,规模缩小:

In [153]: arr = np.round(np.random.uniform(0,1,size = (5,5)),decimals = 0)
     ...: print(arr)
     ...: arr2 = np.cumsum(arr,axis=0)
     ...: print(arr2)
     ...: mask = np.where((arr == 1)&(arr2<=3),1,0)
     ...: print(mask)
     ...: population = np.round(np.random.uniform(0,5,size=(5,5)),decimals=0)
     ...: print(population)
     ...: print(mask==1)
     ...: maskedPop = population[mask==1]
     ...: print(maskedPop)

打印结果 - 我添加了 mask==1 行,因为那是索引的内容:

[[0. 1. 1. 0. 1.]
 [1. 0. 1. 1. 1.]
 [1. 0. 0. 1. 1.]
 [1. 1. 0. 0. 1.]
 [0. 0. 0. 0. 0.]]
[[0. 1. 1. 0. 1.]
 [1. 1. 2. 1. 2.]
 [2. 1. 2. 2. 3.]
 [3. 2. 2. 2. 4.]
 [3. 2. 2. 2. 4.]]
[[0 1 1 0 1]
 [1 0 1 1 1]
 [1 0 0 1 1]
 [1 1 0 0 0]
 [0 0 0 0 0]]
[[0. 5. 2. 2. 2.]
 [1. 4. 2. 4. 0.]
 [2. 3. 3. 2. 2.]
 [4. 4. 3. 1. 3.]
 [4. 2. 2. 1. 5.]]
[[False  True  True False  True]
 [ True False  True  True  True]
 [ True False False  True  True]
 [ True  True False False False]
 [False False False False False]]
[5. 2. 2. 1. 2. 4. 0. 2. 2. 2. 4. 4.]

计算每行或每列 True 的数量。告诉我们这如何保留某种二维结果!

===

我看你已经显示了mask,所以mask==

是一样的
In [158]: mask.astype(bool)
Out[158]: 
array([[False,  True,  True, False,  True],
       [ True, False,  True,  True,  True],
       [ True, False, False,  True,  True],
       [ True,  True, False, False, False],
       [False, False, False, False, False]])

有一个 MaskedArray class 可让您使用具有特定值的数组 'masked-out':

In [161]: np.ma.masked_array(population, mask!=1)
Out[161]: 
masked_array(
  data=[[--, 5.0, 2.0, --, 2.0],
        [1.0, --, 2.0, 4.0, 0.0],
        [2.0, --, --, 2.0, 2.0],
        [4.0, 4.0, --, --, --],
        [--, --, --, --, --]],
  mask=[[ True, False, False,  True, False],
        [False,  True, False, False, False],
        [False,  True,  True, False, False],
        [False, False,  True,  True,  True],
        [ True,  True,  True,  True,  True]],
  fill_value=1e+20)

===

另一种在数组中保留屏蔽值的方法是以某种方式 'zero-out' 值:

In [162]: mpop = population.copy()
In [163]: mpop[mask!=1] = np.nan
In [164]: mpop
Out[164]: 
array([[nan,  5.,  2., nan,  2.],
       [ 1., nan,  2.,  4.,  0.],
       [ 2., nan, nan,  2.,  2.],
       [ 4.,  4., nan, nan, nan],
       [nan, nan, nan, nan, nan]])