Pour être clair, par «supprimer les NaN», vous entendez filtrer uniquement le sous-ensemble de valeurs non nulles . Pas "remplir les NaN avec une certaine valeur (zéro, constant, moyenne, médiane, etc.)"
smci
Réponses:
362
Si vous utilisez numpy pour vos tableaux, vous pouvez également utiliser
x = x[numpy.logical_not(numpy.isnan(x))]
De manière équivalente
x = x[~numpy.isnan(x)]
[Merci à chbrown pour le raccourci ajouté]
Explication
La fonction interne, numpy.isnanrenvoie un tableau booléen / logique qui a Truepartout la valeur qui xn'est pas un nombre. Comme nous voulons le contraire, nous utilisons l'opérateur non logique ~pour obtenir un tableau avec Trues partout qui xest un nombre valide.
Enfin, nous utilisons ce tableau logique pour indexer dans le tableau d'origine x, pour récupérer uniquement les valeurs non NaN.
Ou x = x[~numpy.isnan(x)], ce qui équivaut à la réponse originale de mutzmatron, mais plus court. Dans le cas où vous souhaitez garder vos infinis, sachez que numpy.isfinite(numpy.inf) == False, bien sûr, mais ~numpy.isnan(numpy.inf) == True.
chbrown
8
Pour les personnes qui cherchent à résoudre ce problème avec un ndarray et à maintenir les dimensions, utilisez numpy où :np.where(np.isfinite(x), x, 0)
BoltzmannBrain
1
TypeError: seuls les tableaux scalaires entiers peuvent être convertis en un index scalaire
jusqu'au
1
@towry: cela se produit parce que votre entrée xn'est pas un tableau numpy. Si vous souhaitez utiliser l'indexation logique, ce doit être un tableau - par exemplex = np.array(x)
jmetz
50
filter(lambda v: v==v, x)
fonctionne à la fois pour les listes et le tableau numpy puisque v! = v uniquement pour NaN
Un hack mais particulièrement utile dans le cas où vous filtrez des nans à partir d'un tableau d'objets de types mixtes, tels que des chaînes et des nans.
Austin Richardson
Solution très propre.
Moondra
2
Cela peut sembler intelligent, mais s'il obscurcit la logique et théoriquement d'autres objets (tels que des classes personnalisées) peuvent également avoir cette propriété
Chris_Rands
Également utile car il ne doit xêtre spécifié qu'une seule fois, contrairement aux solutions du type x[~numpy.isnan(x)]. C'est pratique quand xest défini par une expression longue et que vous ne voulez pas encombrer le code en créant une variable temporaire pour stocker le résultat de cette expression longue.
Christian O'Reilly
34
Essaye ça:
import mathprint[value for value in x ifnot math.isnan(value)]
Si vous utilisez numpy, ma réponse et celle de @ lazy1 sont presque un ordre de grandeur plus rapides que la compréhension de la liste - la solution de lazy1 est légèrement plus rapide (bien que techniquement, elle ne renverra pas non plus de valeurs à l'infini).
jmetz
N'oubliez pas les parenthèses :)print ([value for value in x if not math.isnan(value)])
hypers
Si vous utilisez numpy comme la réponse du haut, vous pouvez utiliser cette réponse de compréhension de liste avec le nppackage: renvoie donc votre liste sans les nans:[value for value in x if not np.isnan(value)]
yeliabsalohcin
23
Pour moi, la réponse de @jmetz n'a pas fonctionné, mais l'utilisation de pandas isnull () l'a fait.
J'ai trouvé que la réinitialisation à la même variable (x) ne supprimait pas les valeurs nanos réelles et devait utiliser une variable différente. Le définir sur une variable différente a supprimé les nans. par exemple
Cela est étrange; selon la documentation , l'indexation de tableaux booléens (ce qui est le cas) est sous indexation avancée qui apparemment "renvoie toujours une copie des données", vous devriez donc xécraser avec la nouvelle valeur (c'est-à-dire sans les NaN ...) . Pouvez-vous fournir plus d'informations sur la raison pour laquelle cela pourrait se produire?
jmetz
5
Comme le montrent d'autres
x[~numpy.isnan(x)]
travaux. Mais cela générera une erreur si le type numpy n'est pas un type de données natif, par exemple s'il s'agit d'un objet. Dans ce cas, vous pouvez utiliser des pandas.
La réponse acceptée change de forme pour les tableaux 2D. Je présente ici une solution, en utilisant la fonctionnalité Pandas dropna () . Il fonctionne pour les tableaux 1D et 2D. Dans le cas 2D, vous pouvez choisir la météo pour supprimer la ligne ou la colonne contenant np.nan.
import pandas as pdimport numpy as npdef dropna(arr,*args,**kwarg):assert isinstance(arr, np.ndarray)
dropped=pd.DataFrame(arr).dropna(*args,**kwarg).valuesif arr.ndim==1:
dropped=dropped.flatten()return dropped
x = np.array([1400,1500,1600, np.nan, np.nan, np.nan ,1700])
y = np.array([[1400,1500,1600],[np.nan,0, np.nan],[1700,1800,np.nan]])print('='*20+' 1D Case: '+'='*20+'\nInput:\n',x,sep='')print('\ndropna:\n',dropna(x),sep='')print('\n\n'+'='*20+' 2D Case: '+'='*20+'\nInput:\n',y,sep='')print('\ndropna (rows):\n',dropna(y),sep='')print('\ndropna (columns):\n',dropna(y,axis=1),sep='')print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: '+'='*20+'\nInput:\n',y,sep='')print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')
Résultat:
====================1DCase:====================Input:[1400.1500.1600. nan nan nan 1700.]
dropna:[1400.1500.1600.1700.]====================2DCase:====================Input:[[1400.1500.1600.][ nan 0. nan][1700.1800. nan]]
dropna (rows):[[1400.1500.1600.]]
dropna (columns):[[1500.][0.][1800.]]==================== x[np.logical_not(np.isnan(x))]for2D:====================Input:[[1400.1500.1600.][ nan 0. nan][1700.1800. nan]]
dropna:[1400.1500.1600.1700.]
Bienvenue chez SO! La solution que vous proposez ne répond pas au problème: votre solution remplace NaNs par un grand nombre, tandis que l'OP a demandé de supprimer entièrement les éléments.
Pier Paolo
0
Ceci est mon approche pour filtrer ndarray "X" pour NaNs et infs,
Je crée une carte de lignes sans aucun NaNet infcomme suit:
La réponse de @ jmetz est probablement celle dont la plupart des gens ont besoin; cependant, il donne un tableau unidimensionnel, ce qui rend par exemple inutilisable la suppression de lignes ou de colonnes entières dans les matrices.
Pour ce faire, il faut réduire le tableau logique à une dimension, puis indexer le tableau cible. Par exemple, ce qui suit supprimera les lignes qui ont au moins une valeur NaN:
Réponses:
Si vous utilisez numpy pour vos tableaux, vous pouvez également utiliser
De manière équivalente
[Merci à chbrown pour le raccourci ajouté]
Explication
La fonction interne,
numpy.isnan
renvoie un tableau booléen / logique qui aTrue
partout la valeur quix
n'est pas un nombre. Comme nous voulons le contraire, nous utilisons l'opérateur non logique~
pour obtenir un tableau avecTrue
s partout quix
est un nombre valide.Enfin, nous utilisons ce tableau logique pour indexer dans le tableau d'origine
x
, pour récupérer uniquement les valeurs non NaN.la source
x = x[numpy.isfinite(x)]
x = x[~numpy.isnan(x)]
, ce qui équivaut à la réponse originale de mutzmatron, mais plus court. Dans le cas où vous souhaitez garder vos infinis, sachez quenumpy.isfinite(numpy.inf) == False
, bien sûr, mais~numpy.isnan(numpy.inf) == True
.np.where(np.isfinite(x), x, 0)
x
n'est pas un tableau numpy. Si vous souhaitez utiliser l'indexation logique, ce doit être un tableau - par exemplex = np.array(x)
fonctionne à la fois pour les listes et le tableau numpy puisque v! = v uniquement pour NaN
la source
x
être spécifié qu'une seule fois, contrairement aux solutions du typex[~numpy.isnan(x)]
. C'est pratique quandx
est défini par une expression longue et que vous ne voulez pas encombrer le code en créant une variable temporaire pour stocker le résultat de cette expression longue.Essaye ça:
Pour en savoir plus, lisez la liste des compréhensions .
la source
print ([value for value in x if not math.isnan(value)])
np
package: renvoie donc votre liste sans les nans:[value for value in x if not np.isnan(value)]
Pour moi, la réponse de @jmetz n'a pas fonctionné, mais l'utilisation de pandas isnull () l'a fait.
la source
Faire ce qui précède:
ou
J'ai trouvé que la réinitialisation à la même variable (x) ne supprimait pas les valeurs nanos réelles et devait utiliser une variable différente. Le définir sur une variable différente a supprimé les nans. par exemple
la source
x
écraser avec la nouvelle valeur (c'est-à-dire sans les NaN ...) . Pouvez-vous fournir plus d'informations sur la raison pour laquelle cela pourrait se produire?Comme le montrent d'autres
travaux. Mais cela générera une erreur si le type numpy n'est pas un type de données natif, par exemple s'il s'agit d'un objet. Dans ce cas, vous pouvez utiliser des pandas.
la source
La réponse acceptée change de forme pour les tableaux 2D. Je présente ici une solution, en utilisant la fonctionnalité Pandas dropna () . Il fonctionne pour les tableaux 1D et 2D. Dans le cas 2D, vous pouvez choisir la météo pour supprimer la ligne ou la colonne contenant
np.nan
.Résultat:
la source
Si vous utilisez
numpy
la source
Un moyen le plus simple est:
Documentation: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html
la source
NaN
s par un grand nombre, tandis que l'OP a demandé de supprimer entièrement les éléments.Ceci est mon approche pour filtrer ndarray "X" pour NaNs et infs,
Je crée une carte de lignes sans aucun
NaN
etinf
comme suit:idx est un tuple. C'est la deuxième colonne (
idx[1]
) contient les indices du tableau, où aucun NaN ni inf ne se trouvent à travers la ligne.Ensuite:
filtered_X
contient X sansNaN
niinf
.la source
La réponse de @ jmetz est probablement celle dont la plupart des gens ont besoin; cependant, il donne un tableau unidimensionnel, ce qui rend par exemple inutilisable la suppression de lignes ou de colonnes entières dans les matrices.
Pour ce faire, il faut réduire le tableau logique à une dimension, puis indexer le tableau cible. Par exemple, ce qui suit supprimera les lignes qui ont au moins une valeur NaN:
Voir plus de détails ici .
la source