Je suis actuellement en train de trouver des solutions pour compter le nombre de valeurs manquantes dans un pandas DataFrame
. Celles-ci sont très laides et je me demande s’il existe un meilleur moyen de le faire.
Créons un exemple DataFrame
:
from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Ce que j'ai actuellement c'est
a) Comptage des cellules avec des valeurs manquantes:
>>> sum(df.isnull().values.ravel())
9
b) Comptage des lignes qui ont des valeurs manquantes quelque part:
>>> sum([True for idx,row in df.iterrows() if any(row.isnull())])
3
Pour le second compte, je pense simplement soustraire le nombre de lignes du nombre de lignes renvoyées par dropna
:
In [14]:
from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
df
Out[14]:
one two three
a -0.209453 -0.881878 3.146375
b NaN NaN NaN
c 0.049383 -0.698410 -0.482013
d NaN NaN NaN
e -0.140198 -1.285411 0.547451
f -0.219877 0.022055 -2.116037
g NaN NaN NaN
h -0.224695 -0.025628 -0.703680
In [18]:
df.shape[0] - df.dropna().shape[0]
Out[18]:
3
Le premier pourrait être réalisé en utilisant les méthodes intégrées:
In [30]:
df.isnull().values.ravel().sum()
Out[30]:
9
Horaires
In [34]:
%timeit sum([True for idx,row in df.iterrows() if any(row.isnull())])
%timeit df.shape[0] - df.dropna().shape[0]
%timeit sum(map(any, df.apply(pd.isnull)))
1000 loops, best of 3: 1.55 ms per loop
1000 loops, best of 3: 1.11 ms per loop
1000 loops, best of 3: 1.82 ms per loop
In [33]:
%timeit sum(df.isnull().values.ravel())
%timeit df.isnull().values.ravel().sum()
%timeit df.isnull().sum().sum()
1000 loops, best of 3: 215 µs per loop
1000 loops, best of 3: 210 µs per loop
1000 loops, best of 3: 605 µs per loop
Donc mes alternatives sont un peu plus rapides pour un df de cette taille
Mettre à jour
Donc pour un df avec 80 000 lignes, j'obtiens ce qui suit:
In [39]:
%timeit sum([True for idx,row in df.iterrows() if any(row.isnull())])
%timeit df.shape[0] - df.dropna().shape[0]
%timeit sum(map(any, df.apply(pd.isnull)))
%timeit np.count_nonzero(df.isnull())
1 loops, best of 3: 9.33 s per loop
100 loops, best of 3: 6.61 ms per loop
100 loops, best of 3: 3.84 ms per loop
1000 loops, best of 3: 395 µs per loop
In [40]:
%timeit sum(df.isnull().values.ravel())
%timeit df.isnull().values.ravel().sum()
%timeit df.isnull().sum().sum()
%timeit np.count_nonzero(df.isnull().values.ravel())
1000 loops, best of 3: 675 µs per loop
1000 loops, best of 3: 679 µs per loop
100 loops, best of 3: 6.56 ms per loop
1000 loops, best of 3: 368 µs per loop
En fait, np.count_nonzero
gagne haut la main.
Qu'en est-il de numpy.count_nonzero
:
np.count_nonzero(df.isnull().values)
np.count_nonzero(df.isnull()) # also works
count_nonzero
est assez rapide. Cependant, j'ai construit une trame de données à partir d'un tableau (1000,1000) et inséré de manière aléatoire des valeurs de 100 nan à différentes positions et mesuré les temps des différentes réponses dans iPython:
%timeit np.count_nonzero(df.isnull().values)
1000 loops, best of 3: 1.89 ms per loop
%timeit df.isnull().values.ravel().sum()
100 loops, best of 3: 3.15 ms per loop
%timeit df.isnull().sum().sum()
100 loops, best of 3: 15.7 ms per loop
Ce n’est pas un gain de temps considérable par rapport à la version originale des PO mais peut-être moins déroutant dans le code, votre décision. Il n'y a pas vraiment de différence de temps d'exécution Entre les deux méthodes count_nonzero
(avec et sans .values
).
Une approche simple pour compter les valeurs manquantes dans les lignes ou les colonnes
df.apply(lambda x: sum(x.isnull().values), axis = 0) # For columns
df.apply(lambda x: sum(x.isnull().values), axis = 1) # For rows
Nombre de lignes avec au moins une valeur manquante:
sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
Total manquant:
df.isnull().sum().sum()
Rangées manquantes:
sum(map(any, df.isnull()))
Tant de mauvaises réponses ici. OP a demandé le nombre de lignes avec des valeurs nulles, pas des colonnes.
Voici un meilleur exemple:
from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],columns=['one','two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','asdf'])
print(df)
`Maintenant, il y a évidemment 4 lignes avec des valeurs nulles.
one two three
a -0.571617 0.952227 0.030825
b NaN NaN NaN
c 0.627611 -0.462141 1.047515
d NaN NaN NaN
e 0.043763 1.351700 1.480442
f 0.630803 0.931862 1.500602
g NaN NaN NaN
h 0.729103 -1.198237 -0.207602
asdf NaN NaN NaN
Vous obtiendrez la réponse en tant que 3 (nombre de colonnes avec NaN) si vous avez utilisé certaines des réponses ici. La réponse de Fuentes fonctionne.
Voici comment je l'ai eu:
df.isnull().any(axis=1).sum()
#4
timeit df.isnull().any(axis=1).sum()
#10000 loops, best of 3: 193 µs per loop
'Fuentes':
sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
#4
timeit sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
#1000 loops, best of 3: 677 µs per loop
sum(df.count(axis=1) < len(df.columns))
, le nombre de lignes comportant moins de non nuls que de colonnes.
Par exemple, le cadre de données suivant comporte deux lignes avec des valeurs manquantes.
>>> df = pd.DataFrame({"a":[1, None, 3], "b":[4, 5, None]})
>>> df
a b
0 1 4
1 NaN 5
2 3 NaN
>>> df.count(axis=1)
0 2
1 1
2 1
dtype: int64
>>> df.count(axis=1) < len(df.columns)
0 False
1 True
2 True
dtype: bool
>>> sum(df.count(axis=1) < len(df.columns))
2
Je pense que si vous voulez juste jeter un oeil sur le résultat, il y a un pandc func pandas.DataFrame.count .
Revenons donc à cette rubrique, en utilisant df.count(axis=1)
, et vous obtiendrez le résultat comme suit:
a 3
b 0
c 3
d 0
e 3
f 3
g 0
h 3
dtype: int64
Il vous dira combien de paramètres non-NaN dans chaque ligne. Pendant ce temps, -(df.count(axis=1) - df.shape[1])
indique
a 0
b 3
c 0
d 3
e 0
f 0
g 3
h 0
dtype: int64