Как правильно маскировать массив NumPy 2D?

скажем, у меня есть двумерный массив координат, который выглядит что-то вроде

x = array([[1,2],[2,3],[3,4]])

ранее в моей работе до сих пор я создал маску, которая в конечном итоге выглядит как

mask = [False,False,True]

когда я пытаюсь использовать эту маску на 2D координатном векторе, я получаю ошибку

newX = np.ma.compressed(np.ma.masked_array(x,mask))

>>>numpy.ma.core.MaskError: Mask and data not compatible: data size 
   is 6, mask size is 3.`

что имеет смысл, я полагаю. Поэтому я попытался просто использовать следующую маску:

mask2 = np.column_stack((mask,mask))
newX = np.ma.compressed(np.ma.masked_array(x,mask2))

и что я получаю закрыть:

>>>array([1,2,2,3])

к тому, что я ожидал бы (и хочу):

>>>array([[1,2],[2,3]])

там должен быть более простой способ сделать это?

4 ответов


это то, что вы ищете?

import numpy as np
x[~np.array(mask)]
# array([[1, 2],
#        [2, 3]])

или numpy маскированный массив:

newX = np.ma.array(x, mask = np.column_stack((mask, mask)))
newX

# masked_array(data =
#  [[1 2]
#  [2 3]
#  [-- --]],
#              mask =
#  [[False False]
#  [False False]
#  [ True  True]],
#        fill_value = 999999)

код x is 3x2:

In [379]: x
Out[379]: 
array([[1, 2],
       [2, 3],
       [3, 4]])

сделать 3 элемента логической маски:

In [380]: rowmask=np.array([False,False,True])

это можно использовать для выбора строк, где это True, или где это False. В обоих случаях результат 2d:

In [381]: x[rowmask,:]
Out[381]: array([[3, 4]])

In [382]: x[~rowmask,:]
Out[382]: 
array([[1, 2],
       [2, 3]])

это без использования подкласса MaskedArray. Чтобы сделать такой массив, нам нужна маска, которая соответствует x в форме. Не предусмотрено маскировки только одного измерения.

In [393]: xmask=np.stack((rowmask,rowmask),-1)  # column stack

In [394]: xmask
Out[394]: 
array([[False, False],
       [False, False],
       [ True,  True]], dtype=bool)

In [395]: np.ma.MaskedArray(x,xmask)
Out[395]: 
masked_array(data =
 [[1 2]
 [2 3]
 [-- --]],
             mask =
 [[False False]
 [False False]
 [ True  True]],
       fill_value = 999999)

применение compressed что производит массив распущенной: array([1, 2, 2, 3])

поскольку маскировка поэлементно, она может маскировать один элемент в строке 1, 2 в строке 2 и т. д. Так вообще compressing, удаляя маскированные элементы, не даст 2d-массив. Сплющенная форма-единственный общий выбор.

np.ma имеет смысл, когда есть рассеяние значений в масках. Это не имеет большого значения, если вы хотите выбрать или отменить выбор целых строк или столбцов.

===============

здесь являются более типичными маскированными массивами:

In [403]: np.ma.masked_inside(x,2,3)
Out[403]: 
masked_array(data =
 [[1 --]
 [-- --]
 [-- 4]],
             mask =
 [[False  True]
 [ True  True]
 [ True False]],
       fill_value = 999999)

In [404]: np.ma.masked_equal(x,2)
Out[404]: 
masked_array(data =
 [[1 --]
 [-- 3]
 [3 4]],
             mask =
 [[False  True]
 [ True False]
 [False False]],
       fill_value = 2)

In [406]: np.ma.masked_outside(x,2,3)
Out[406]: 
masked_array(data =
 [[-- 2]
 [2 3]
 [3 --]],
             mask =
 [[ True False]
 [False False]
 [False  True]],
       fill_value = 999999)

поскольку ни одно из этих решений работал для меня, я думал написать, что решение, может быть, это будет полезно для кого-то другого. Я использую python 3.мы с x работали над двумя 3D массивами. Один, который я называю data_3D содержит плавающие значения записей в сканировании мозга, а другой,template_3D содержит целые числа, представляющие области мозга. Я хотел выбрать эти значения из data_3D соответствует целому числу region_code по состоянию на template_3D:

my_mask = np.in1d(template_3D, region_code).reshape(template_3D.shape)
data_3D_masked = data_3D[my_mask]

что дает мне массив 1D только соответствующих записей.


в вашем последнем примере, проблема не в маске. Это ваше использование compressed. Из docstring compressed:

Return all the non-masked data as a 1-D array.

так compressed сглаживает немаскированные значения в 1-d массив. (Это так, потому что нет никакой гарантии, что сжатые данные будут иметь N-мерные структуры.)

взгляните на маскированный массив, прежде чем сжимать его:

In [8]: np.ma.masked_array(x, mask2)

Out[8]: 
masked_array(data =
 [[1 2]
 [2 3]
 [-- --]],
             mask =
 [[False False]
 [False False]
 [ True  True]],
       fill_value = 999999)