Question Comment supprimer des lignes de Pandas DataFrame dont la valeur dans certaines colonnes est NaN


j'ai un DataFrame:

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

Ensuite, je veux juste les enregistrements dont EPS n'est pas NaN, C'est, df.drop(....) retournera le dataframe comme ci-dessous:

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

Comment je fais ça?


433
2017-11-16 09:17


origine


Réponses:


Ne pas drop. Il suffit de prendre des lignes où EPS est fini:

df = df[np.isfinite(df['EPS'])]

351
2017-11-16 09:34



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

... considérez également la solution proposée par Wouter dans son commentaire original. La capacité à gérer les données manquantes, y compris dropna(), est construit dans les pandas explicitement. Outre les performances potentiellement améliorées par rapport à la réalisation manuelle, ces fonctions sont également accompagnées d'une variété d'options qui peuvent être 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 y a aussi d'autres options (Voir la documentation à http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html), y compris la suppression de colonnes au lieu de lignes.

Assez pratique!


606
2017-11-17 20:27



Je sais que cela a déjà été répondu, mais juste pour une solution purement pandas à cette question spécifique, par opposition à la description générale d'Aman (qui était magnifique) et au cas où quelqu'un d'autre se produirait à ce sujet:

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

83
2018-04-23 05:37



Vous pouvez utiliser ceci:

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

28
2017-08-02 16:28



Vous pouvez utiliser la méthode dataframe notnull ou inverse de Isnull, ou numpy.isnan:

In [332]: df[df.EPS.notnull()]
Out[332]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN


In [334]: df[~df.EPS.isnull()]
Out[334]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN


In [347]: df[~np.isnan(df.EPS)]
Out[347]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN

19
2017-12-04 07:01



Le plus simple de toutes les solutions:

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

La solution ci-dessus est bien meilleure que np.isfinite ()


16
2017-11-23 12:08



encore une autre solution qui utilise le fait que np.nan != np.nan:

In [149]: df.query("EPS == EPS")
Out[149]:
                 STK_ID  EPS  cash
STK_ID RPT_Date
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN

8
2018-04-20 21:15



Il peut être ajouté à ce que "&" peut être utilisé pour ajouter des conditions supplémentaires, par ex.

df = df[(df.EPS > 2.0) & (df.EPS <4.0)]

Notez que lors de l'évaluation des déclarations, les pandas ont besoin de parenthèses.


0
2018-03-15 15:33



Pour une raison quelconque, aucune des réponses précédemment soumises n'a fonctionné pour moi. Cette solution de base a fait:

df = df[df.EPS >= 0]

Bien sûr, cela va aussi faire tomber les lignes avec des nombres négatifs. Donc, si vous voulez ceux-ci, il est probablement intelligent d'ajouter cela après.

df = df[df.EPS <= 0]

-1
2017-10-09 18:00