Comment vérifier si une valeur est NaN dans un Pandas DataFrame


Réponses:


578

La réponse de jwilner est parfaite . J'explorais pour voir s'il y avait une option plus rapide, car d'après mon expérience, la somme des tableaux plats est (étrangement) plus rapide que de compter. Ce code semble plus rapide:

df.isnull().values.any()

Par exemple:

In [2]: df = pd.DataFrame(np.random.randn(1000,1000))

In [3]: df[df > 0.9] = pd.np.nan

In [4]: %timeit df.isnull().any().any()
100 loops, best of 3: 14.7 ms per loop

In [5]: %timeit df.isnull().values.sum()
100 loops, best of 3: 2.15 ms per loop

In [6]: %timeit df.isnull().sum().sum()
100 loops, best of 3: 18 ms per loop

In [7]: %timeit df.isnull().values.any()
1000 loops, best of 3: 948 µs per loop

df.isnull().sum().sum()est un peu plus lent, mais bien sûr, a des informations supplémentaires - le nombre de NaNs.


1
Merci pour les repères temporels. Il est surprenant qu'il pandasn'y ait pas de fonction intégrée pour cela. C'est vrai d'après @ JGreenwell's post qui df.describe()peut le faire, mais pas de fonction directe.
hlin117

2
Je viens de chronométrer df.describe()(sans trouver de NaNs). Avec une baie de 1 000 x 1 000, un seul appel prend 1,15 seconde.
hlin117

3
: 1, Aussi, df.isnull().values.sum()est un peu plus rapide quedf.isnull().values.flatten().sum()
Zero

Ah, bonne capture @JohnGalt - je vais changer ma solution pour supprimer l' .flatten()affiche. Merci.
S Anand

6
Vous n'avez pas essayé df.isnull().values.any(), pour moi c'est plus rapide que les autres.
CK1

178

Vous avez plusieurs options.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] = np.nan
df.iloc[5,3] = np.nan
df.iloc[7:9,5] = np.nan

Maintenant, le bloc de données ressemble à ceci:

          0         1         2         3         4         5
0  0.520113  0.884000  1.260966 -0.236597  0.312972 -0.196281
1 -0.837552       NaN  0.143017  0.862355  0.346550  0.842952
2 -0.452595       NaN -0.420790  0.456215  1.203459  0.527425
3  0.317503 -0.917042  1.780938 -1.584102  0.432745  0.389797
4 -0.722852  1.704820 -0.113821 -1.466458  0.083002  0.011722
5 -0.622851 -0.251935 -1.498837       NaN  1.098323  0.273814
6  0.329585  0.075312 -0.690209 -3.807924  0.489317 -0.841368
7 -1.123433 -1.187496  1.868894 -2.046456 -0.949718       NaN
8  1.133880 -0.110447  0.050385 -1.158387  0.188222       NaN
9 -0.513741  1.196259  0.704537  0.982395 -0.585040 -1.693810
  • Option 1 : df.isnull().any().any()- Cela renvoie une valeur booléenne

Vous savez isnull()ce qui retournerait une trame de données comme celle-ci:

       0      1      2      3      4      5
0  False  False  False  False  False  False
1  False   True  False  False  False  False
2  False   True  False  False  False  False
3  False  False  False  False  False  False
4  False  False  False  False  False  False
5  False  False  False   True  False  False
6  False  False  False  False  False  False
7  False  False  False  False  False   True
8  False  False  False  False  False   True
9  False  False  False  False  False  False

Si vous le faites df.isnull().any(), vous pouvez trouver uniquement les colonnes qui ont des NaNvaleurs:

0    False
1     True
2    False
3     True
4    False
5     True
dtype: bool

Un autre .any()vous dira si l'un des éléments ci-dessus estTrue

> df.isnull().any().any()
True
  • Option 2 : df.isnull().sum().sum()- Cela retourne un entier du nombre total de NaNvaleurs:

Cela fonctionne de la même manière que le .any().any()fait, en donnant d'abord une somme du nombre de NaNvaleurs dans une colonne, puis la somme de ces valeurs:

df.isnull().sum()
0    0
1    2
2    0
3    1
4    0
5    2
dtype: int64

Enfin, pour obtenir le nombre total de valeurs NaN dans le DataFrame:

df.isnull().sum().sum()
5

Pourquoi ne pas utiliser à la .any(axis=None)place de .any().any()?
Georgy

57

Pour savoir quelles lignes contiennent des NaN dans une colonne spécifique:

nan_rows = df[df['name column'].isnull()]

17
Pour en savoir quelles lignes n'ont pas NaN dans une colonne spécifique: non_nan_rows = df[df['name column'].notnull()].
Elmex80s

49

Si vous avez besoin de savoir combien de lignes contiennent "un ou plusieurs NaNs":

df.isnull().T.any().T.sum()

Ou si vous devez retirer ces lignes et les examiner:

nan_rows = df[df.isnull().T.any().T]

4
Je pense que nous n'avons pas besoin du 2ème T
YOBEN_S


18

Pour ajouter une réponse brillante à Hobs, je suis très nouveau sur Python et Pandas, veuillez donc signaler si je me trompe.

Pour savoir quelles lignes ont des NaN:

nan_rows = df[df.isnull().any(1)]

effectuerait la même opération sans avoir besoin de transposer en spécifiant l'axe de any () comme 1 pour vérifier si «True» est présent dans les lignes.


Cela supprime deux transpositions! Aimez votre any(axis=1)simplification concise .
plaques de cuisson

12

Syntaxe super simple: df.isna().any(axis=None)

À partir de la version 0.23.2 , vous pouvez utiliser DataFrame.isna+ DataFrame.any(axis=None)axis=Nonespécifie la réduction logique sur l'ensemble du DataFrame.

# Setup
df = pd.DataFrame({'A': [1, 2, np.nan], 'B' : [np.nan, 4, 5]})
df
     A    B
0  1.0  NaN
1  2.0  4.0
2  NaN  5.0

df.isna()

       A      B
0  False   True
1  False  False
2   True  False

df.isna().any(axis=None)
# True

Alternatives utiles

numpy.isnan
Une autre option performante si vous utilisez des versions plus anciennes de pandas.

np.isnan(df.values)

array([[False,  True],
       [False, False],
       [ True, False]])

np.isnan(df.values).any()
# True

Alternativement, vérifiez la somme:

np.isnan(df.values).sum()
# 2

np.isnan(df.values).sum() > 0
# True

Series.hasnans
Vous pouvez également appeler de manière itérative Series.hasnans. Par exemple, pour vérifier si une seule colonne contient des NaN,

df['A'].hasnans
# True

Et pour vérifier si une colonne contient des NaN, vous pouvez utiliser une compréhension avec any(qui est une opération de court-circuit).

any(df[c].hasnans for c in df)
# True

C'est en fait très rapide.


10

Puisqu'aucun n'a mentionné, il y a juste une autre variable appelée hasnans.

df[i].hasnansaffichera Truesi une ou plusieurs des valeurs de la série pandas sont NaN, Falsesinon. Notez que ce n'est pas une fonction.

pandas version '0.19.2' et '0.20.2'


6
Cette réponse est incorrecte. Les séries Pandas ont cet attribut, mais pas les DataFrames. Si df = DataFrame([1,None], columns=['foo']), alors df.hasnansjettera un AttributeError, mais df.foo.hasnansreviendra True.
Nathan Thompson

7

Puisqu'il pandasdoit le découvrir DataFrame.dropna(), j'ai jeté un œil pour voir comment ils l'implémentent et j'ai découvert qu'ils en faisaient usage DataFrame.count(), qui compte toutes les valeurs non nulles dans le DataFrame. Cf. code source pandas . Je n'ai pas évalué cette technique, mais je pense que les auteurs de la bibliothèque ont probablement fait un choix judicieux sur la façon de le faire.


6

laissez - dfêtre le nom du Pandas et dataframe toute valeur qui est numpy.nanune valeur nulle.

  1. Si vous voulez voir quelles colonnes ont des valeurs nulles et lesquelles ne le sont pas (juste vrai et faux)
    df.isnull().any()
  2. Si vous voulez voir uniquement les colonnes qui ont des valeurs nulles
    df.loc[:, df.isnull().any()].columns
  3. Si vous voulez voir le nombre de null dans chaque colonne
    df.isna().sum()
  4. Si vous voulez voir le pourcentage de null dans chaque colonne

    df.isna().sum()/(len(df))*100
  5. Si vous souhaitez voir le pourcentage de null dans les colonnes uniquement avec null: df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100

EDIT 1:

Si vous voulez voir visuellement où vos données manquent:

import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])

Si vous voulez voir le nombre de null dans chaque colonne ... Cela semble insensé, pourquoi ne pas le faire df.isna().sum()?
AMC

4

Il suffit d'utiliser math.isnan (x) , de renvoyer True si x est un NaN (pas un nombre) et False sinon.


4
Je ne pense pas que ça math.isnan(x)va fonctionner quand xest un DataFrame. Vous obtenez une TypeError à la place.
hlin117

Pourquoi utiliseriez-vous cela sur l'une des alternatives?
AMC

4
df.isnull().sum()

Cela vous donnera le nombre de toutes les valeurs de NaN présentes dans les colonnes respectives du DataFrame.


Non, cela vous donnera une série qui mappera les noms de colonnes à leur nombre respectif de valeurs NA.
AMC

Corrigé, ma faute: p
Adarsh ​​singh

3

Voici une autre façon intéressante de trouver nul et de le remplacer par une valeur calculée

    #Creating the DataFrame

    testdf = pd.DataFrame({'Tenure':[1,2,3,4,5],'Monthly':[10,20,30,40,50],'Yearly':[10,40,np.nan,np.nan,250]})
    >>> testdf2
       Monthly  Tenure  Yearly
    0       10       1    10.0
    1       20       2    40.0
    2       30       3     NaN
    3       40       4     NaN
    4       50       5   250.0

    #Identifying the rows with empty columns
    nan_rows = testdf2[testdf2['Yearly'].isnull()]
    >>> nan_rows
       Monthly  Tenure  Yearly
    2       30       3     NaN
    3       40       4     NaN

    #Getting the rows# into a list
    >>> index = list(nan_rows.index)
    >>> index
    [2, 3]

    # Replacing null values with calculated value
    >>> for i in index:
        testdf2['Yearly'][i] = testdf2['Monthly'][i] * testdf2['Tenure'][i]
    >>> testdf2
       Monthly  Tenure  Yearly
    0       10       1    10.0
    1       20       2    40.0
    2       30       3    90.0
    3       40       4   160.0
    4       50       5   250.0

3

J'ai utilisé ce qui suit et saisissez-le en une chaîne et en vérifiant la valeur nan

   (str(df.at[index, 'column']) == 'nan')

Cela me permet de vérifier une valeur spécifique dans une série et de ne pas simplement retourner si elle est contenue quelque part dans la série.


Y a-t-il un avantage à utiliser ce sur pandas.isna()?
AMC

2

Le mieux serait d'utiliser:

df.isna().any().any()

Voici pourquoi . Ainsi isna()est utilisé pour définir isnull(), mais les deux sont bien sûr identiques.

C'est encore plus rapide que la réponse acceptée et couvre tous les tableaux de panda 2D.


1

Ou vous pouvez utiliser .info()sur DFtels que:

df.info(null_counts=True) qui renvoie le nombre de lignes non nulles dans des colonnes telles que:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 3276314 entries, 0 to 3276313
Data columns (total 10 columns):
n_matches                          3276314 non-null int64
avg_pic_distance                   3276314 non-null float64


0
df.apply(axis=0, func=lambda x : any(pd.isnull(x)))

Vérifie pour chaque colonne si elle contient Nan ou non.


Pourquoi utiliser cela sur l'une des solutions intégrées?
AMC

0

On peut voir les valeurs nulles présentes dans l'ensemble de données en générant heatmap en utilisant le module Seaborn heatmap

import pandas as pd
import seaborn as sns
dataset=pd.read_csv('train.csv')
sns.heatmap(dataset.isnull(),cbar=False)

-1

Vous pouvez non seulement vérifier s'il existe des «NaN», mais également obtenir le pourcentage de «NaN» dans chaque colonne à l'aide des éléments suivants,

df = pd.DataFrame({'col1':[1,2,3,4,5],'col2':[6,np.nan,8,9,10]})  
df  

   col1 col2  
0   1   6.0  
1   2   NaN  
2   3   8.0  
3   4   9.0  
4   5   10.0  


df.isnull().sum()/len(df)  
col1    0.0  
col2    0.2  
dtype: float64

-2

Selon le type de données que vous traitez, vous pouvez également obtenir le nombre de valeurs de chaque colonne tout en effectuant votre EDA en définissant dropna sur False.

for col in df:
   print df[col].value_counts(dropna=False)

Fonctionne bien pour les variables catégorielles, pas tant lorsque vous avez de nombreuses valeurs uniques.


Je pense que c'est inefficace. Les fonctions intégrées des pandas sont plus soignées / laconiques. Évite l'encombrement du bloc-notes ipython.
Koo

Il n'y a aucun intérêt à utiliser cela sur les solutions intégrées.
AMC
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.