J'ai un problème et je ne trouve aucune solution sur le web ou dans la documentation, même si je pense que c'est très banal.
Que veux-je faire?
J'ai une trame de données comme celle-ci
CLASS FEATURE1 FEATURE2 FEATURE3
X A NaN NaN
X NaN A NaN
B A A A
Je veux regrouper par le libellé ( CLASSE ) et afficher le nombre de valeurs NaN qui sont comptées dans chaque fonctionnalité pour que cela ressemble à ceci. Le but de ceci est d'avoir une idée générale de la façon dont les valeurs manquantes sont réparties entre les différentes classes.
CLASS FEATURE1 FEATURE2 FEATURE3
X 1 1 2
B 0 0 0
Je sais comment recevoir la quantité de non nulle - Valeurs - df.groupby['CLASS'].count()
Existe-t-il quelque chose de similaire pour les valeurs NaN -?
J'ai essayé de soustraire le count () de la taille () mais il a renvoyé une sortie non formatée remplie avec la valeur NaN
Calculez un masque avec isna
, puis groupez et trouvez la somme:
df.drop('CLASS', 1).isna().groupby(df.CLASS, sort=False).sum().reset_index()
CLASS FEATURE1 FEATURE2 FEATURE3
0 X 1.0 1.0 2.0
1 B 0.0 0.0 0.0
Une autre option consiste à soustraire le size
du count
en utilisant rsub
le long du 0e axe pour la soustraction alignée sur l'indice:
df.groupby('CLASS').count().rsub(df.groupby('CLASS').size(), axis=0)
Ou,
g = df.groupby('CLASS')
g.count().rsub(g.size(), axis=0)
FEATURE1 FEATURE2 FEATURE3
CLASS
B 0 0 0
X 1 1 2
Il y a pas mal de bonnes réponses, alors voici quelques timeits
pour votre lecture:
df_ = df
df = pd.concat([df_] * 10000)
%timeit df.drop('CLASS', 1).isna().groupby(df.CLASS, sort=False).sum()
%timeit df.set_index('CLASS').isna().sum(level=0)
%%timeit
g = df.groupby('CLASS')
g.count().rsub(g.size(), axis=0)
11.8 ms ± 108 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
9.47 ms ± 379 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
6.54 ms ± 81.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Les performances réelles dépendent de vos données et de votre configuration, votre kilométrage peut donc varier.
Vous pouvez utiliser set_index
et sum
:
df.set_index('CLASS').isna().sum(level=0)
Sortie:
FEATURE1 FEATURE2 FEATURE3
CLASS
X 1.0 1.0 2.0
B 0.0 0.0 0.0
Utilisation de la différence entre count
et size
g=df.groupby('CLASS')
-g.count().sub(g.size(),0)
FEATURE1 FEATURE2 FEATURE3
CLASS
B 0 0 0
X 1 1 2
Et nous pouvons transformer cette question en une question plus générique, comment compter le nombre de NaN
dans la trame de données avec la boucle for
pd.DataFrame({x: y.isna().sum()for x , y in g }).T.drop('CLASS',1)
Out[468]:
FEATURE1 FEATURE2 FEATURE3
B 0 0 0
X 1 1 2