Как удалить строки Pandas DataFrame, значение которых в определенном столбце равно NaN

У меня есть этот DataFrame и я хочу только записи, у которых в столбце EPS нет 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

... т.е. что-то вроде df.drop(....) для получения этого результирующего кадра данных:

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

Как я могу это сделать?

Ответ 1

Не drop. Просто возьмите строки, где EPS конечно:

import numpy as np

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

Ответ 2

Этот вопрос уже разрешен, но...

... также рассмотрим решение, предложенное Wouter в его оригинальном комментарии. Способность обрабатывать отсутствующие данные, включая dropna(), встроена в pandas явно. Помимо потенциально улучшенной производительности при выполнении вручную, эти функции также имеют множество вариантов, которые могут быть полезны.

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

Существуют также другие варианты (см. документы в http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html), включая удаление столбцов вместо строк.

Довольно удобно!

Ответ 3

Я знаю, что на это уже был дан ответ, но только ради чисто решения pandas к этому конкретному вопросу, в отличие от общего описания из Aman (что было замечательно), и в случае, если кто-то еще случится на этом:

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

Ответ 4

Вы можете использовать это:

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

Ответ 5

Самый простой из всех решений:

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

Вышеупомянутое решение лучше, чем использование np.isfinite()

Ответ 6

Вы можете использовать метод dataframe notnull или инвертировать isnull, или 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

Ответ 7

Вы можете использовать дропна

пример

Удалите строки, где отсутствует хотя бы один элемент.

df=df.dropna()

Определите, в каких столбцах искать пропущенные значения.

df=df.dropna(subset=['column1', 'column1'])

Смотрите это для большего количества примеров

Примечание: параметр оси dropna устарел с версии 0.23.0:

Ответ 9

еще одно решение, которое использует тот факт, что 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

Ответ 10

Или (проверьте для NaN с isnull, затем используйте ~ чтобы сделать противоположность не NaN):

df=df[~df['EPS'].isnull()]

Сейчас:

print(df)

Является:

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

Ответ 11

Этот ответ намного проще, чем все выше :)

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

Ответ 12

Он может быть добавлен при этом '&' может использоваться для добавления дополнительных условий, например.

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

Обратите внимание, что при оценке операторов pandas требуется скобка.

Ответ 13

По какой-то причине ни один из ранее представленных ответов не работал у меня. Это базовое решение:

df = df[df.EPS >= 0]

Хотя, конечно, это также приведет к сокращению строк с отрицательными числами. Поэтому, если вы хотите, чтобы это, вероятно, было разумно добавить и после этого.

df = df[df.EPS <= 0]

Ответ 14

Одним из решений может быть

df = df[df.isnull().sum(axis=1) <= Cutoff Value]

Другим способом может быть

df= df.dropna(thresh=(df.shape[1] - Cutoff_value))

Я надеюсь, что это полезно.