2015-05-13 6 views
5

Ho un semplice array 3D a1, e il suo analogo mascherato a2:`numpy.mean` utilizzato con una tupla come` fuori asse` argomento: non funziona con una gamma mascherato

import numpy 

a1 = numpy.array([[[ 0.00, 0.00, 0.00], 
        [ 0.88, 0.80, 0.78], 
        [ 0.75, 0.78, 0.77]], 

        [[ 0.00, 0.00, 0.00], 
        [ 3.29, 3.29, 3.30], 
        [ 3.27, 3.27, 3.26]], 

        [[ 0.00, 0.00, 0.00], 
        [ 0.41, 0.42, 0.40], 
        [ 0.42, 0.43, 0.41]]]) 


a2 = numpy.ma.masked_equal(a1, 0.) 

voglio eseguire la media di questo array lungo più assi contemporaneamente (questo è un caratteristico, uso documentato di axis argomento numpy.mean, si veda ad esempio here per un esempio):

numpy.mean(a1, axis=(0, 1)) 

questo funziona bene con 0.123.865,553842 millions 383.105.577.445,89321 milioni, ma ottengo il seguente errore con l'array mascherato a2:

TypeError: tuple indices must be integers, not tuple 

e ottengo lo stesso errore con la versione mascherata numpy.ma.mean(a2, axis=(0, 1)), o se unmasko la matrice attraverso a2[a2.mask]=0.

sto usando una tupla per l'argomento axis in numpy.mean come è in realtà non codificato (questo comando viene applicato su array con potenially diverso numero di dimensioni, secondo la quale la tupla è atto).

Problema riscontrato con numpy versione 1.9.1 e 1.9.2.

+0

Potrebbe fornire un esempio di copia e incolla? – atomh33ls

+0

Secondo [docs] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.mean.html), l'argomento dell'asse dovrebbe essere un int. Che cosa fa passare una tupla invece di una int? – ypx

+0

Non dovresti usare la versione ['ma' di' mean'] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.mean.html) per un argomento di array mascherato ? – user2357112

risposta

5

Per un argomento MaskedArray, numpy.mean chiamate MaskedArray.mean, che non supporta una tupla axis argomento. È possibile ottenere il comportamento corretto da reimplementare MaskedArray.mean in termini di operazioni che fanno le tuple di supporto per axis:

def mean(a, axis=None): 
    if a.mask is numpy.ma.nomask: 
     return super(numpy.ma.MaskedArray, a).mean(axis=axis) 

    counts = numpy.logical_not(a.mask).sum(axis=axis) 
    if counts.shape: 
     sums = a.filled(0).sum(axis=axis) 
     mask = (counts == 0) 
     return numpy.ma.MaskedArray(data=sums * 1./counts, mask=mask, copy=False) 
    elif counts: 
     # Return scalar, not array 
     return a.filled(0).sum(axis=axis) * 1./counts 
    else: 
     # Masked scalar 
     return numpy.ma.masked 

o, se siete disposti a fare affidamento su MaskedArray.sum lavorare con una tupla axis (che probabilmente sei, data che si sta utilizzando un comportamento non documentato di numpy.mean),

def mean(a, axis=None): 
    if a.mask is numpy.ma.nomask: 
     return super(numpy.ma.MaskedArray, a).mean(axis=axis) 

    sums = a2.sum(axis=axis) 
    counts = numpy.logical_not(a.mask).sum(axis=axis) 
    result = sums * 1./counts 

dove stiamo contando su MaskedArray.sum per gestire la maschera.

Ho solo leggermente testato queste funzioni; prima di usarli, assicurati che funzionino effettivamente e scrivi alcuni test. Ad esempio, se l'output è 0-dimensionale e non ci sono valori mascherati, se l'output è un MaskedArray 0D o uno scalare dipende dal fatto che la maschera di input sia nomask o una matrice di tutti i falsi. È lo stesso del comportamento predefinito MaskedArray.mean, ma potrebbe non essere quello che desideri; Sospetto che il comportamento predefinito sia un bug.

Problemi correlati