1000 votes

Comment supprimer les lignes d'un DataFrame Pandas dont la valeur d'une certaine colonne est NaN ?

J'ai ceci DataFrame et ne veulent que les enregistrements dont EPS La colonne n'est pas NaN :

>>> df
                 STK_ID  EPS  cash
STK_ID RPT_Date                   
601166 20111231  601166  NaN   NaN
600036 20111231  600036  NaN    12
600016 20111231  600016  4.3   NaN
601009 20111231  601009  NaN   NaN
601939 20111231  601939  2.5   NaN
000001 20111231  000001  NaN   NaN

...c'est-à-dire quelque chose comme df.drop(....) pour obtenir ce cadre de données résultant :

                  STK_ID  EPS  cash
STK_ID RPT_Date                   
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN

Comment je fais ça ?

24 votes

215 votes

df.dropna(subset = ['column1_name', 'column2_name', 'column3_name'])

1036voto

Aman Points 3440

Cette question est déjà résolue, mais...

...envisagez également la solution proposée par Wouter dans son commentaire original . La capacité de traiter les données manquantes, notamment dropna() est intégré explicitement à pandas. Outre l'amélioration potentielle des performances par rapport à une exécution manuelle, ces fonctions sont également dotées de diverses options qui peuvent s'avérer utiles.

In [24]: df = pd.DataFrame(np.random.randn(10,3))

In [25]: df.iloc[::2,0] = np.nan; df.iloc[::4,1] = np.nan; df.iloc[::3,2] = np.nan;

In [26]: df
Out[26]:
          0         1         2
0       NaN       NaN       NaN
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
4       NaN       NaN  0.050742
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
8       NaN       NaN  0.637482
9 -0.310130  0.078891       NaN

In [27]: df.dropna()     #drop all rows that have any NaN values
Out[27]:
          0         1         2
1  2.677677 -1.466923 -0.750366
5 -1.250970  0.030561 -2.678622
7  0.049896 -0.308003  0.823295

In [28]: df.dropna(how='all')     #drop only if ALL columns are NaN
Out[28]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
4       NaN       NaN  0.050742
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
8       NaN       NaN  0.637482
9 -0.310130  0.078891       NaN

In [29]: df.dropna(thresh=2)   #Drop row if it does not have at least two values that are **not** NaN
Out[29]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
5 -1.250970  0.030561 -2.678622
7  0.049896 -0.308003  0.823295
9 -0.310130  0.078891       NaN

In [30]: df.dropna(subset=[1])   #Drop only if NaN in specific column (as asked in the question)
Out[30]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
9 -0.310130  0.078891       NaN

Il existe également d'autres options (voir la documentation à l'adresse suivante http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html ), y compris l'élimination des colonnes au lieu des lignes.

Très pratique !

345 votes

vous pouvez également utiliser df.dropna(subset = ['column_name']) . J'espère que cela épargnera à au moins une personne les 5 secondes supplémentaires de "qu'est-ce que je fais mal". Excellente réponse, +1

11 votes

@JamesTobin, je viens de passer 20 minutes à écrire une fonction pour cela ! La documentation officielle était très énigmatique : "Des étiquettes le long d'autres axes à prendre en compte, par exemple, si vous supprimez des lignes, ce serait une liste de colonnes à inclure". Je n'ai pas pu comprendre ce que cela signifiait...

0 votes

df.dropna(subset = ['column_name']) est exactement ce que je recherchais ! Merci !

1012voto

eumiro Points 56644

Ne laissez pas tomber, prenez juste les rangs où EPS n'est pas NA :

df = df[df['EPS'].notna()]

487 votes

Je recommande d'utiliser pandas.notnull au lieu de np.isfinite

16 votes

Y a-t-il un avantage à indexer et à copier plutôt qu'à déposer ?

10 votes

Crée une erreur : TypeError : ufunc 'isfinite' non supporté pour les types d'entrée, et les entrées n'ont pas pu être coerciées en toute sécurité vers des types supportés selon la règle de casting ''safe''.

131voto

Kirk Hadley Points 61

Je sais qu'on a déjà répondu à cette question, mais juste pour avoir une solution purement pandas à cette question spécifique, par opposition à la description générale d'Aman (qui était merveilleuse) et au cas où quelqu'un d'autre tomberait dessus :

import pandas as pd
df = df[pd.notnull(df['EPS'])]

11 votes

En fait, la réponse spécifique serait : df.dropna(subset=['EPS']) (basé sur la description générale d'Aman, bien sûr cela fonctionne aussi)

2 votes

notnull C'est également ce que Wes (auteur de Pandas) a suggéré dans son commentaire sur une autre réponse.

0 votes

C'est peut-être une question de débutant. Mais quand je fais un df[pd.notnull(...) ou df.dropna l'index est abandonné. Ainsi, s'il y avait une valeur nulle dans l'index de ligne 10 dans un df de longueur 200. Le cadre de données après l'exécution de la fonction drop a des valeurs d'index de 1 à 9, puis de 11 à 200. Comment le "réindexer" ?

75voto

Joe Points 4777

Vous pouvez utiliser ceci :

df.dropna(subset=['EPS'], how='all', inplace=True)

22 votes

how='all' est redondant ici, parce que vous ne sous-ensemblez le dataframe qu'avec un seul champ, donc les deux 'all' et 'any' aura le même effet.

40voto

Gil Baggio Points 2137

La plus simple de toutes les solutions :

filtered_df = df[df['EPS'].notnull()]

La solution ci-dessus est bien meilleure que l'utilisation de np.isfinite().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X