Dans les pandas Python, quel est le meilleur moyen de vérifier si un DataFrame a une (ou plusieurs) valeur NaN?
Je connais la fonction pd.isnan
, mais cela retourne un DataFrame de booléens pour chaque élément. Ce post ici ne répond pas exactement à ma question non plus.
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, sommer 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 a bien sûr des informations supplémentaires - le nombre de NaNs
.
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 cadre 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
df.isnull().any().any()
- Ceci retourne une valeur booléenneVous connaissez le isnull()
qui renverrait un cadre de données comme celui-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 définissez df.isnull().any()
, vous pouvez trouver uniquement les colonnes qui ont des valeurs NaN
:
0 False
1 True
2 False
3 True
4 False
5 True
dtype: bool
.any()
vous indiquera si l’un des éléments ci-dessus est True
> df.isnull().any().any()
True
df.isnull().sum().sum()
- Cette fonction renvoie un entier du nombre total de valeurs NaN
:Ceci fonctionne de la même manière que le .any().any()
, en donnant d'abord une somme du nombre de valeurs NaN
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
Pour savoir quelles lignes contiennent des NaN dans une colonne spécifique:
nan_rows = df[df['name column'].isnull()]
Si vous avez besoin de savoir combien de lignes il y a avec "un ou plusieurs NaN
s":
df.isnull().T.any().T.sum()
Ou si vous devez extraire ces lignes et les examiner:
nan_rows = df[df.isnull().T.any().T]
df.isnull().any().any()
devrait le faire.
Ajoutant à la réponse brillante de Hobs, je suis très novice en Python et en Pandas, alors veuillez indiquer 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.
Comme aucun n'a mentionné, il n'y a qu'une autre variable appelée hasnans
.
df[i].hasnans
affichera True
si une ou plusieurs des valeurs de la série pandas est NaN, False
sinon. Notez que ce n'est pas une fonction.
version pandas '0.19.2' et '0.20.2'
Puisque pandas
doit le découvrir pour DataFrame.dropna()
, j'ai jeté un coup d'œil à la façon dont ils l'ont implémenté et découvert qu'ils utilisaient DataFrame.count()
, qui compte toutes les valeurs non nulles dans DataFrame
. Cf. code source des pandas . Je n’ai pas évalué cette technique, mais j’imagine que les auteurs de la bibliothèque ont probablement fait le bon choix.
Il suffit d'utiliser math.isnan (x) , Renvoie True si x est un NaN (pas un nombre) et False sinon.
À partir de la v0.23.2 , vous pouvez utiliser DataFrame.isna
+ DataFrame.any(axis=None)
où axis=None
indique une 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
Une autre option performante que vous pouvez utiliser est numpy.isnan
:
np.isnan(df.values)
array([[False, True],
[False, False],
[ True, False]])
np.isnan(df.values).any()
# True
Sinon, vérifiez la somme:
np.isnan(df.values).sum()
# 2
np.isnan(df.values).sum() > 0
# True
Vous pouvez également appeler de manière itérative Series.hasnans
. Par exemple, pour vérifier si une seule colonne a des NaN,
df['A'].hasnans
# True
Et pour vérifier si la colonne any contient des NaN, vous pouvez utiliser la compréhension avec any
(opération consistant à court-circuiter).
any(df[c].hasnans for c in df)
# True
C'est en fait très rapide.
Voici un autre moyen intéressant de trouver null 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
Ou vous pouvez utiliser .info()
sur la DF
tel que:
df.info(null_counts=True)
qui retourne le nombre de lignes non nuls dans une colonne telle 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
soit df
le nom du Pandas DataFrame et toute valeur qui est numpy.nan
est une valeur nulle.
df.isnull().any()
df.loc[:, df.isnull().any()].columns
df.loc[:, list(df.loc[:, df.isnull().any()].columns)].isnull().sum()
df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100
EDIT 1: Si vous voulez voir où vos données manquent visuellement:import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])
J'utilise ce qui suit et le transforme en chaîne et recherche la valeur nan
(str(df.at[index, 'column']) == 'nan')
Cela me permet de vérifier une valeur spécifique dans une série et pas seulement de revenir si elle est contenue quelque part dans la série.
Le mieux serait d'utiliser:
df.isna().any().any()
Voici pourquoi . Donc, isna()
est utilisé pour définir isnull()
, mais les deux sont identiques, bien sûr.
Ceci est encore plus rapide que la réponse acceptée et couvre tous les tableaux de panda 2D.
df.isnull (). sum () Ceci vous donnera le nombre de toutes les valeurs NaN dans le DataFrame
df.apply(axis=0, func=lambda x : any(pd.isnull(x)))
Va vérifier pour chaque colonne si elle contient Nan ou non.
Selon le type de données que vous utilisez, vous pouvez également obtenir le nombre de valeurs de chaque colonne lors de l'exécution de 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, moins quand vous avez plusieurs valeurs uniques.