Formulation du problème
Vous utilisez le np.nanmean()
de NumPy fonction dans votre code qui est censée ignorer NaN
valeurs lors du calcul de la moyenne d'un tableau NumPy.
import numpy as np a = np.array([np.NaN, np.NaN]) mean = np.nanmean(a)
Mais lors de son utilisation, NumPy lève un RuntimeWarning: Mean of empty slice
messages :
Warning (from warnings module): File "C:\Users\xcent\Desktop\code.py", line 3 mean = np.nanmean(a) RuntimeWarning: Mean of empty slice
Quelle est la raison de cet avertissement et comment y remédier ?
Solution + Explication
La raison pour laquelle cet avertissement se produit est que vous appliquez le np.nanmean()
fonction sur un tableau vide. La fonction ne provoque pas d'erreur si le tableau contient au moins une valeur non NaN :
>>> np.nanmean([0.42, np.NaN, np.NaN]) 0.42
Si au moins un élément est une valeur numérique, la moyenne est clairement définie :somme sur tous les éléments qui ne sont pas NaN
et diviser par le nombre de ces éléments.
Cependant, si tous les éléments d'un tableau NumPy sont np.NaN
, NumPy lève le RuntimeWarning
:
>>> np.nanmean([np.NaN, np.NaN]) Warning (from warnings module): File "C:\Users\xcent\Desktop\code.py", line 1 import numpy as np RuntimeWarning: Mean of empty slice nan
Pourtant, vous pouvez également voir qu'il génère toujours la valeur de retour :not-a-number ou nan
.
Comme ce cas limite est correctement défini et sans ambiguïté, cela a amené certains programmeurs à se demander s'il était même logique d'émettre cet avertissement.
? À mon avis, émettre un avertissement n'a pas beaucoup de sens dans le cas du np.nanmean()
fonction. D'après Python's Zen of Python, nous savons que "explicite vaut mieux qu'implicite" . Donc, soit déclenchez une exception et laissez le programmeur la gérer directement, soit laissez-la simplement passer si tout est correctement défini.
Si, comme moi, vous êtes agacé par cet avertissement, vous pouvez simplement le supprimer :
Comment supprimer RuntimeWarning ?
Le gestionnaire de contexte warnings.catch_warnings
supprime l'avertissement, mais seulement si vous anticipez effectivement son arrivée. Sinon, vous risquez de manquer quelques RuntimeWarning
supplémentaires s vous n'avez pas vu venir.
import numpy as np import warnings with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) mean = np.nanmean([np.NaN, np.NaN]) print(mean)
La sortie est sans avertissement :
nan
Cependant, vous devez être sûr que c'est le seul avertissement qui peut apparaître dans le with
environnement de bloc. Sinon, vous risquez de manquer certains avertissements importants, comme nous l'avons déjà mentionné.
Un moyen plus sûr serait probablement d'utiliser warnings.filterwarnings(action='ignore', message='Mean of empty slice')
laisser passer non anticipé RuntimeWarning
s.
Solution alternative :vérifier les valeurs entièrement NaN
Si vous n'aimez pas la solution précédente pour son manque de brièveté, comme moi, vous pouvez également vérifier de manière défensive si le tableau ne contient que NaN
valeurs. Si c'est le cas, il vous suffit de coder en dur la solution pour qu'elle soit nan
sans même exécuter le np.nanmean()
fonction qui génère le message d'avertissement.
Le code suivant crée une fonction personnalisée numpy_nan_mean()
qui prend un tableau en entrée et renvoie la moyenne ou nan
si toutes les valeurs sont np.NaN
.
import numpy as np def numpy_nan_mean(a): return np.NaN if np.all(a!=a) else np.nanmean(a) print(numpy_nan_mean([np.NaN, np.NaN, np.NaN])) # nan print(numpy_nan_mean([np.NaN, np.NaN, 1.23])) # 1.23
Le code utilise l'observation qui compare deux np.NaN
les valeurs renverront toujours False
. Uniquement si toutes les valeurs sont np.Nan
la fonction appellera-t-elle np.all(a!=a)
renvoie True
.
>>> np.NaN == np.NaN False
Nous utilisons l'opérateur uniligne ternaire x if y else z
pour retourner np.NaN
dans ce cas particulier au lieu d'exécuter le np.nanmean()
fonction qui produirait l'avertissement.
RuntimeWarning - Calcul de la moyenne à partir d'un tableau vide
Fait intéressant, il existe une autre source de ce message d'avertissement :si vous essayez de calculer le np.nanmean([])
d'un tableau NumPy vide ou d'une liste vide :
>>> np.nanmean([]) Warning (from warnings module): File "C:\Users\xcent\Desktop\code.py", line 1 import numpy as np RuntimeWarning: Mean of empty slice nan
Vous pouvez résoudre ce problème en vérifiant d'abord si le tableau est vide et en ne calculant la moyenne que s'il n'est pas vide :
>>> def nanmean(a): if a.size == 0: return np.NaN else: return np.nanmean(a) >>> nanmean(np.array([])) nan >>> nanmean(np.array([1, 2, 3])) 2.0