특정 열의 값이 NaN 인 Pandas DataFrame의 행을 삭제하는 방법


753

나는 이것을 가지고 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

어떻게합니까?



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

답변:


655

EPS가 NA가 아닌 행을 가져 가십시오.

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

470
pandas.notnull대신 사용 하는 것이 좋습니다np.isfinite
Wes McKinney

11
삭제보다 인덱싱 및 복사에 이점이 있습니까?
Robert Muil

9
형식 오류 : 오류를 작성 ufunc 'isFinite에'입력 유형에 대해 지원되지 및 입력 안전하게 캐스팅 규칙 ''안전 ''에 따라 지원되는 모든 형태의 강제 변환 할 수없는
필립 바르

4
@ wes-mckinney이 경우 pandas.notnull보다 dropna ()가 더 나은 선택인지 알려주십시오. 그렇다면 왜 그렇습니까?
stormfield

4
@PhilippSchwarz이 오류는 열 ( EPS예에서)에 의해 소화 할 수없는 문자열 또는 다른 유형이 포함 된 경우 발생합니다 np.isfinite(). pandas.notnull()이것을 더 관대하게 처리하는 것이 좋습니다 .
normanius

902

이 질문은 이미 해결되었지만 ...

... 또한 원래 의견 에서 Wouter가 제안한 솔루션을 고려하십시오 . 를 포함하여 누락 된 데이터를 처리하는 기능 dropna()은 팬더에 명시 적으로 내장되어 있습니다. 수동으로 수행하는 것보다 잠재적으로 향상된 성능 외에도 이러한 기능에는 유용한 다양한 옵션이 있습니다.

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의 문서 참조 ).

꽤 편리합니다!


281
당신은 또한 사용할 수 있습니다 df.dropna(subset = ['column_name']). 희망은 적어도 한 사람이 '내가 잘못하고있는 것'을 5 초 더 절약 할 수 있기를 바랍니다. 위대한 답변, +1
James Tobin

10
@JamesTobin, 방금 20 분 동안 함수를 작성했습니다! 공식 문서 는 매우 비밀 스러웠습니다. "예를 들어 행을 삭제하는 경우 포함 할 열 목록이됩니다." 나는 그들이 무엇을 의미하는지 이해할 수 없었습니다.
osa

df.dropna(subset = ['column_name'])내가 찾던 것입니다! 감사!
amalik2205

123

나는 이것이 이미 답변되었지만 아만 (일반적으로 훌륭함)의 일반적인 설명과는 달리이 특정 질문에 대한 순수한 판다 솔루션을 위해 다른 사람 이이 문제를 겪을 경우를 대비하여 알고 있습니다.

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

10
사실, 특정의 대답은 다음과 같습니다 df.dropna(subset=['EPS'])(아만의 일반적인 설명에 따라, 물론 이것은 또한 작업을 수행 중)
요리스

2
notnull또한 Wes (Pandas의 저자)가 다른 답변에 대한 그의 의견에서 제안한 것입니다.
fantabolous

이것은 아마도 멍청한 질문 일 것입니다. 그러나 df [pd.notnull (...) 또는 df.dropna를 수행하면 인덱스가 삭제됩니다. 따라서 길이 200의 df에서 행 인덱스 10에 널값이있는 경우 드롭 함수를 실행 한 후 데이터 프레임의 인덱스 값은 1-9,
11-200입니다.

당신은 또한 당신이 이름을 모른다면 번호가 매겨진 열이 될 df[pd.notnull(df[df.columns[INDEX]])]곳을 INDEX할 수 있습니다
ocean800

60

이것을 사용할 수 있습니다 :

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

18
how='all'둘 다 너무 dataframe 단 하나 개의 필드를 부분 집합 있기 때문에, 중복 여기 'all''any'동일한 효과를 얻을 수 있습니다.
Anton Protopopov

35

가장 간단한 솔루션 :

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

위의 솔루션은 np.isfinite ()를 사용하는 것보다 낫습니다.


22

당신은 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

18

간단하고 쉬운 방법

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

출처 : https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html


inplace=True기괴한 주제이며에 영향을 미치지 않습니다 DataFrame.dropna(). 참조 : github.com/pandas-dev/pandas/issues/16529
AMC

이 답변은 @Joe의 답변과 어떻게 다릅니 까? 또한 inplace는 결국 더 이상 사용되지 않으므로 전혀 사용하지 않는 것이 좋습니다.
7

10

다음과 같은 사실을 사용하는 또 다른 솔루션 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


2

많은 수의 열을 가진 데이터 세트에서 null 값을 포함하는 열 수와 그렇지 않은 열 수를 확인하는 것이 좋습니다.

print("No. of columns containing null values")
print(len(df.columns[df.isna().any()]))

print("No. of columns not containing null values")
print(len(df.columns[df.notna().all()]))

print("Total no. of columns in the dataframe")
print(len(df.columns))

예를 들어 내 데이터 프레임에는 82 개의 열이 있었고 그 중 19 개에는 적어도 하나의 null 값이 포함되었습니다.

또한 null 값이 더 많은 열에 따라 열과 행을 자동으로 제거 할 수도 있습니다
. 지능적으로 수행하는 코드는 다음과 같습니다.

df = df.drop(df.columns[df.isna().sum()>len(df.columns)],axis = 1)
df = df.dropna(axis = 0).reset_index(drop=True)

참고 : 위의 코드는 모든 null 값을 제거합니다. 널값을 원하면 이전에 처리하십시오.



0

'&'를 사용하여 추가 조건을 추가 할 수 있습니다. 예 :

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

문장을 평가할 때 팬더는 괄호가 필요합니다.


2
죄송하지만 OP는 다른 것을 원합니다. Btw, 코드가 잘못되었습니다 ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().. 괄호를 추가해야 df = df[(df.EPS > 2.0) & (df.EPS <4.0)]하지만이 질문에 대한 답변은 아닙니다.
jezrael

-1

어떤 이유로 든 이전에 제출 된 답변 중 어느 것도 나를 위해 일하지 않았습니다. 이 기본 솔루션은 다음을 수행했습니다.

df = df[df.EPS >= 0]

물론 음수로 행을 삭제합니다. 따라서 원하는 경우 나중에 추가하는 것이 현명합니다.

df = df[df.EPS <= 0]

이것은 완전히 다른 일을합니다.
AMC

-1

해결책 중 하나는

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

다른 방법은

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

이것들이 유용하기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.