web-dev-qa-db-fra.com

Comment masquer correctement un tableau 2D numpy?

Disons que j'ai un tableau bidimensionnel de coordonnées qui ressemble à quelque chose

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

Auparavant, dans mon travail jusqu'à présent, j'ai généré un masque qui finit par ressembler à quelque chose comme

mask = [False,False,True]

Lorsque j'essaie d'utiliser ce masque sur le vecteur de coordonnées 2D, j'obtiens une erreur

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.`

ce qui est logique, je suppose. J'ai donc essayé d'utiliser simplement le masque suivant à la place:

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

Et ce que je reçois est proche:

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

à ce à quoi je m'attendais (et que je veux):

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

Il doit y avoir un moyen plus simple de le faire?

18
Anonymous

Est-ce ce que vous recherchez?

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

Ou de tableau masqué 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)
12
Psidom

Votre x est 3x2:

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

Créez un masque booléen à 3 éléments:

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

Cela peut être utilisé pour sélectionner les lignes où c'est vrai ou où c'est faux. Dans les deux cas, le résultat est 2d:

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

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

Ceci sans utiliser la sous-classe MaskedArray. Pour créer un tel tableau, nous avons besoin d'un masque qui correspond à x en forme. Il n'est pas prévu de masquer une seule dimension.

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)

Appliquer compressed à cela produit un tableau défilé: array([1, 2, 2, 3])

Le masquage étant élément par élément, il pourrait masquer un élément de la ligne 1, 2 de la ligne 2, etc. En général, compressing, la suppression des éléments masqués ne donnera pas de tableau 2d. La forme aplatie est le seul choix général.

np.ma Est plus logique lorsqu'il y a une dispersion de valeurs masquées. Cela n'a pas beaucoup de valeur si vous souhaitez sélectionner ou désélectionner des lignes ou des colonnes entières.

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

Voici des tableaux masqués plus typiques:

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)
5
hpaulj

Puisqu'aucune de ces solutions n'a fonctionné pour moi, j'ai pensé écrire ce que la solution a fait, peut-être qu'elle sera utile à quelqu'un d'autre. J'utilise python 3.x et j'ai travaillé sur deux tableaux 3D. L'un, que j'appelle data_3D contient des valeurs flottantes d'enregistrements dans une analyse cérébrale, et l'autre, template_3D contient des nombres entiers qui représentent des régions du cerveau. Je voulais choisir ces valeurs parmi data_3D correspondant à un entier region_code selon template_3D:

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

ce qui me donne un tableau 1D uniquement des enregistrements pertinents.

2
CrossEntropy

Dans votre dernier exemple, le problème n'est pas le masque. C'est votre utilisation de compressed. De la docstring de compressed:

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

Donc compressed aplatit les valeurs non masquées dans un tableau 1-d. (Il doit le faire, car il n'y a aucune garantie que les données compressées auront une structure à n dimensions.)

Jetez un œil au tableau masqué avant de le compresser:

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)
1
Warren Weckesser