2015-04-17 12 views
30

sagen, dass ich zwei numpy Arrays konstruieren:Mittelwert, nanmean und Warnung: Mittelwert der leeren Scheibe

a = np.array([np.NaN, np.NaN]) 
b = np.array([np.NaN, np.NaN, 3]) 

Jetzt finde ich, dass np.mean kehrt nan für beide a und b:

>>> np.mean(a) 
nan 
>>> np.mean(b) 
nan 

Seit numpy 1.8 (veröffentlicht am 20. April 2016), wurden wir mit nanmean gesegnet, die nan Werte ignoriert:

>>> np.nanmean(b) 
3.0 

Wenn jedoch das Array hat nichts abernan Werte, wirft es eine Warnung:

>>> np.nanmean(a) 
nan 
C:\python-3.4.3\lib\site-packages\numpy\lib\nanfunctions.py:598: RuntimeWarning: Mean of empty slice 
    warnings.warn("Mean of empty slice", RuntimeWarning) 

Ich mag keine Warnungen zu unterdrücken; Gibt es eine bessere Funktion, die ich verwenden kann, um das Verhalten von nanmean ohne diese Warnung zu erhalten?

+1

Warum ist die Warnung ein Problem? –

+7

Ich muss zugeben, die Warnung macht keinen Sinn. Ein sinnvolles Verhalten ist die konsequente Rückgabe von 'nan'; der andere, konsequent eine Ausnahme zu erheben. Eine Warnung ist so eine Antwort. – Amadan

+0

Was ist los mit der Unterdrückung von Warnungen? Sie müssen es nicht im großen Stil tun - unterdrücken Sie einfach die Warnung, wo Sie wissen, dass Sie 'np.nanmean' in einem Array aller NaNs verwenden könnten. –

Antwort

32

ich kann wirklich keinen guten Grund sehen nicht nur die Warnung unterdrücken.

Der sicherste Weg, um den warnings.catch_warnings Kontext-Manager zu verwenden, wäre die Warnung zu unterdrücken nur dort, wo Sie es antizipieren auftritt - auf diese Weise können Sie nicht verpassen zusätzliche jede RuntimeWarnings, die unerwartet in einem anderen Teil des Codes erhöht werden könnte:

import numpy as np 
import warnings 

x = np.ones((1000, 1000)) * np.nan 

# I expect to see RuntimeWarnings in this block 
with warnings.catch_warnings(): 
    warnings.simplefilter("ignore", category=RuntimeWarning) 
    foo = np.nanmean(x, axis=1) 

@ Lösung würde die kumpel auch funktionieren, aber letztlich keine zusätzlichen Schritte, die Sie zu ergreifen, um haben Rechen np.nanmean auf einem Array aller NaNs zu vermeiden, werden einige zusätzliche Overhead verursachen, dass Sie das nur durch Unterdrückung von vermeiden könnte Warnung. Auch Ihre Absicht wird viel deutlicher im Code widergespiegelt.

+2

Dies ist eine nutzlose Warnung und es gibt keine 'seterr' für sie wie andere Fehler – dashesy

7

Ein NaN Wert ist so definiert, nicht auf sich selbst gleich:

>>> float('nan') == float('nan') 
False 
>>> np.NaN == np.NaN 
False 

Sie ein Python-bedingte verwenden können und die Eigenschaft eines nan nie sich selbst gleich zu sein, dieses Verhalten zu erhalten:

>>> a = np.array([np.NaN, np.NaN]) 
>>> b = np.array([np.NaN, np.NaN, 3]) 
>>> np.NaN if np.all(a!=a) else np.nanmean(a) 
nan 
>>> np.NaN if np.all(b!=b) else np.nanmean(b) 
3.0 

Sie können auch tun:

import warnings 
import numpy as np 

a = np.array([np.NaN, np.NaN]) 
b = np.array([np.NaN, np.NaN, 3]) 

with warnings.catch_warnings(): 
    warnings.filterwarnings('error') 
    try: 
     x=np.nanmean(a) 
    except RuntimeWarning: 
     x=np.NaN  
print x  
+0

Das funktioniert für eindimensionale numpy Arrays. Leider habe ich in meinem tatsächlichen Anwendungsfall multidimensionale Daten und ich nehme den Mittelwert entlang einer Dimension. z.B. 'np.nanmean (np.array ([[np.NaN], [3]]), 1)' –

+0

Fügen Sie dann entsprechendes Slicing hinzu. Außerdem scheint 'np.nanmean (np.array ([[np.NaN], [3]]), 1)' wie erwartet zu funktionieren ... – dawg

+1

Warum einen 'try' /' except' Block verwenden? 'np.nanmean (a)' wird sowieso 'np.nan' zurückgeben. –