web-dev-qa-db-fra.com

moyenne, nanomètre et avertissement: moyenne de la tranche vide

Disons que je construis deux tableaux numpy:

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

Maintenant, je trouve que np.mean renvoie nan pour a et b:

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

Depuis numpy 1.8 (sortie le 20 avril 2016), nous avons la chance de disposer de nanmean , qui ignore les valeurs de nan:

>>> np.nanmean(b)
3.0

Cependant, lorsque le tableau n'a rien mais nan valeurs, un avertissement est émis:

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

Je n'aime pas supprimer les avertissements. Existe-t-il une meilleure fonction que je peux utiliser pour obtenir le comportement de nanmean sans cet avertissement?

50
Michael Currie

Je ne vois vraiment aucune bonne raison de ne pas supprimer l'avertissement.

Le moyen le plus sûr serait d'utiliser le warnings.catch_warnings gestionnaire de contexte pour supprimer l’avertissement uniquement là où vous l’anticipez - de cette manière, vous ne manquerez aucun RuntimeWarnings supplémentaire susceptible d’être levé de manière inattendue dans une autre partie de votre code:

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)

La solution de @ dawg fonctionnerait aussi, mais en fin de compte, vous devrez prendre des mesures supplémentaires pour éviter de calculer np.nanmean sur un tableau de tous les réseaux NaN générera des frais supplémentaires que vous pourriez éviter en supprimant simplement l'avertissement. De plus, votre intention sera beaucoup plus clairement reflétée dans le code.

49
ali_m

Une valeur NaN est définie pour ne pas être égale à elle-même:

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

Vous pouvez utiliser un Python conditionnel et la propriété d'un nan n'étant jamais égale à elle-même pour obtenir ce comportement:

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

Vous pouvez aussi faire:

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    
12
dawg