Python >> Tutoriel Python >  >> Python Tag >> NumPy

[Résolu] NumPy RuntimeWarning :moyenne de la tranche vide

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