特定の列の値がNaNであるPandas DataFrameの行を削除する方法


754

私はこれを持って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 14

回答:


655

ドロップしないでください。EPSがNAではない行を取得してください。

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

470
pandas.notnull代わりに使用することをお勧めしますnp.isfinite
ウェスマッキーニー

11
ドロップよりもインデックス作成とコピーに利点はありますか?
Robert Muil、2015

9
Creates Error:TypeError:ufunc 'isfinite' not supported for the input types、and cannot be安全に強制された型にサポートされた型に従ってキャスト規則 '' safe ''
Philipp Schwarz

4
@ wes-mckinneyは、この場合、pandas.notnullよりもdropna()の方が適しているかどうかをお知らせください。もしそうなら、なぜですか?
ストームフィールド2017

4
@PhilippSchwarzこのエラーは、列(EPS例)に文字列またはで消化できない他の型が含まれている場合に発生しnp.isfinite()ます。私はpandas.notnull()これをより寛大に扱うことができるものを使うことを勧めます。
ノルマニウス2018

902

この質問はすでに解決されていますが...

...また、ウーターが最初のコメントで提案した解決策を検討してください。を含む欠落データを処理する機能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のドキュメントを参照)。

かなり便利!


282
も使用できますdf.dropna(subset = ['column_name'])。少なくとも1人の人が「何が悪いのか」という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'])(アマンの一般的な説明に基づくと、もちろんこれでも機能します)
joris

2
notnullWes(Pandasの作者)が別の回答についてのコメントで提案したものでもあります。
14

これは多分noobの質問です。しかし、df [pd.notnull(...)またはdf.dropnaを実行すると、インデックスが削除されます。したがって、長さ200のdfの行インデックス10にnull値があった場合。drop関数を実行した後のデータフレームには、1〜9、11〜200のインデックス値があります。とにかく「再インデックス」するには
Aakash Gupta

名前がわからない場合は、番号が付けられた列のdf[pd.notnull(df[df.columns[INDEX]])]場所INDEXを指定することもできます
ocean800

60

あなたはこれを使うことができます:

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

18
how='all'あなたは両方のように、1つのフィールドだけを持つデータフレームをサブセット化するので冗長では、ここにある'all''any'同じ効果を持つことになります。
アントンプロト

35

すべてのソリューションの中で最も単純:

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

上記の解決策はnp.isfinite()を使用するよりも優れています


22

データフレームメソッド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は最終的には非推奨になるため、まったく使用しないことをお勧めします。
misantroop

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列には少なくとも1つの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値を削除します。null値が必要な場合は、前にそれらを処理します。


別の質問リンク
Pradeep Singh

0

'&'を使用して追加の条件を追加できるときに追加できます。

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

ステートメントを評価するとき、パンダには括弧が必要です。


2
申し訳ありませんが、OPは別のものを求めています。ところで、あなたのコードは間違っています、戻り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 2016年

-1

何らかの理由で、以前に提出された回答がどれも私にとってうまくいきませんでした。この基本的な解決策は:

df = df[df.EPS >= 0]

もちろん、負の数の行も削除されます。そのため、これらを追加したい場合は、おそらくこれを後で追加するのも賢明です。

df = df[df.EPS <= 0]

これはまったく違うことをしますか?
AMC

-1

解決策の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.