2016-07-02 11 views
5

ho notato che le numpy masked-array mean method rendimenti diversi tipi quando probabilmente non dovrebbero:numpy.ma (mascherato) di matrice significare metodo ha tipo di ritorno inconsitent

import numpy as np 

A = np.ma.masked_equal([1,1,0], value=0) 
B = np.ma.masked_equal([1,1,1], value=0) # no masked values 

type(A.mean()) 
#numpy.float64 
type(B.mean()) 
#numpy.ma.core.MaskedArray 

Altri numpy.ma.core.MaskedArray metodi sembrano essere coerenti

type(A.sum()) == type(B.sum()) 
# True 
type(A.prod()) == type(B.prod()) 
# True 
type(A.std()) == type(B.std()) 
# True 
type(A.mean()) == type(B.mean()) 
# False 

Qualcuno può spiegarlo?

UPDATE: Come sottolineato nei commenti

C = np.ma.masked_array([1, 1, 1], mask=[False, False, False]) 
type(C.mean()) == type(A.mean()) 
# True 
+0

Se restituisce un tipo diverso SOLO quando non si mascherano valori, non si tratta di un'incoerenza, è solo un caso speciale ... Hai controllato il tipo di B immediatamente dopo aver chiamato masked_equal? –

+1

Nota che se 'C = np.ma.masked_array ([1, 1, 1], mask = [False, False, False])', allora 'type (C.mean())' è lo stesso di 'type (A.mean()) '. –

+0

Interessante davvero – dermen

risposta

1

B.mask inizia con:

if self._mask is nomask: 
     result = super(MaskedArray, self).mean(axis=axis, dtype=dtype) 

np.ma.nomask è False.

Questo è il caso per la vostra B:

masked_array(data = [1 1 1], 
      mask = False, 
     fill_value = 0) 

Per A la maschera è un array che corrisponde al data in termini di dimensioni. In B è uno scalare, False e mean lo gestisce come un caso speciale.

Ho bisogno di scavare un po 'di più per vedere cosa questo implica.

In [127]: np.mean(B) 
Out[127]: 
masked_array(data = 1.0, 
      mask = False, 
     fill_value = 0) 

In [141]: super(np.ma.MaskedArray,B).mean() 
Out[141]: 
masked_array(data = 1.0, 
      mask = False, 
     fill_value = 0) 

Non sono sicuro che sia d'aiuto; esistono alcuni riferimenti circolari tra i metodi np.ndarray e la funzione np ei metodi np.ma, che rendono difficile identificare esattamente quale codice viene utilizzato. È come se usasse il metodo compilato mean, ma non è ovvio come gestisca il mascheramento.

mi chiedo se l'intento è quello di utilizzare

np.mean(B.data) # or 
B.data.mean() 

e il metodo super recuperare non è l'approccio giusto.

In ogni caso, lo stesso array, ma con una maschera vettoriale restituisce lo scalare.

In [132]: C 
Out[132]: 
masked_array(data = [1 1 1], 
      mask = [False False False], 
     fill_value = 0) 

In [133]: C.mean() 
Out[133]: 1.0 

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

Cercando questo metodo senza il collegamento nomask, solleva un errore dopo

 dsum = self.sum(axis=axis, dtype=dtype) 
     cnt = self.count(axis=axis) 
     if cnt.shape ==() and (cnt == 0): 
      result = masked 
     else: 
      result = dsum * 1./cnt 

self.count restituisce uno scalare nel caso nomask, ma uno np.int32 nel mascheramento normale. Quindi le strozzature cnt.shape.

trace è l'unico altro metodo mascherato che prova questo "collegamento" super(MaskedArray...). C'è chiaramente qualcosa di pesante nel codice medio.

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

Rilevante problema bug: https://github.com/numpy/numpy/issues/5769

Secondo che la stessa questione è stata sollevata qui l'anno scorso: Testing equivalence of means of Numpy MaskedArray instances raises attribute error

Sembra che ci siano molti problemi di mascheramento, non solo con mean. Potrebbero esserci delle correzioni nel master di sviluppo ora o nel prossimo futuro.