web-dev-qa-db-fra.com

Meilleure façon de compter le nombre de lignes avec les valeurs manquantes dans un pandas DataFrame

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'])

enter image description here

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
18
Sebastian

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.

24
EdChum

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).

10
Paul Joireman

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)
7
Alvaro Fuentes

Total manquant:

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

Rangées manquantes:

sum(map(any, df.isnull()))
3
ely

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
1
ConanG

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
0
W.P. McNeill

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
0
ruining.z