2017-10-09 19 views
1

私はパンダで作業しており、複数のフィールドにわたって複数のフィルタをデータフレームに適用したいと考えています。パンダ:複数の列のフィルタ

私は別のより複雑なデータフレームで作業していますが、私はこの質問のためにcontexを単純化しています。ここではサンプルデータフレームのためのセットアップは次のとおりです。このデータフレームに一つのフィルタを適用する

dates = pd.date_range('20170101', periods=16) 
rand_df = pd.DataFrame(np.random.randn(16,4), index=dates, columns=list('ABCD')) 

十分に文書化し、シンプルさ:

rand_df.loc[lambda df: df['A'] < 0] 

ラムダは、単純なブール式のように見えるので。次のことをするのは魅力的です。ブール式ではなく、呼び出し可能なので、これは機能しません。複数のブール式をブール式として組み合わせることはできません。

rand_df.loc[lambda df: df['A'] < 0 and df[‘B’] < 0] 

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-31-dfa05ab293f9> in <module>() 
----> 1 rand_df.loc[lambda df: df['A'] < 0 and df['B'] < 0] 

これを正常に実装するには2つの方法があります。潜在的な回答にそれらを追加するので、ソリューションとして直接コメントすることができます。しかし、私はこれらのどちらもパンダのデータフレームをフィルタリングするための非常に標準的なアプローチであるとは本当に確信していないので、他のアプローチを募集したいと思います。ここで

+0

UN-DUPLICATEを使用して評価をスピードアップすることができます。これは重複としてラベル付けされた質問は、私の質問に答えません。しかし、これほどきれいではありません。この質問には、データがCSVから読み込まれるなどの余分な文脈があります。これはきれいな例です。ここでコードを自分のREPLに直接貼り付け、回答を出して投稿することができます。非常に短期間では、この質問には重複した候補者よりも多くの回答がありました。したがって、私は再開するのが理にかなっていると思います。 –

+0

質問は全く同じで、重複した回答はpandasの作成者によって書かれたので、データフレームをフィルタリングする最良の方法であると確信しています。 – DJK

+0

ありがとうございます。私はWes McKinneyが答えたPandasの質問に特別な重みを付けるべきだと謙虚に指摘しました。 –

答えて

2

アプローチは、「鎖は」 'LOC' 操作を使用することです:

rand_df.loc[lambda df: df['A'] < 0].loc[lambda df: df['B'] < 0] 
3
rand_df[(rand_df.A < 0) & (rand_df.B <0)] 
5
In [3]: rand_df.query("A < 0 and B < 0") 
Out[3]: 
        A   B   C   D 
2017-01-02 -0.701682 -1.224531 -0.273323 -1.091705 
2017-01-05 -1.262971 -0.531959 -0.997451 -0.070095 
2017-01-06 -0.065729 -1.427199 1.202082 0.136657 
2017-01-08 -1.445050 -0.367112 -2.617743 0.496396 
2017-01-12 -1.273692 -0.456254 -0.668510 -0.125507 

か:あなたは多くの例があります

In [6]: rand_df[rand_df[['A','B']].lt(0).all(1)] 
Out[6]: 
        A   B   C   D 
2017-01-02 -0.701682 -1.224531 -0.273323 -1.091705 
2017-01-05 -1.262971 -0.531959 -0.997451 -0.070095 
2017-01-06 -0.065729 -1.427199 1.202082 0.136657 
2017-01-08 -1.445050 -0.367112 -2.617743 0.496396 
2017-01-12 -1.273692 -0.456254 -0.668510 -0.125507 

PS in

1

ここにフィルタリングを行うメソッドを記述することを含むアプローチです。私は、いくつかのフィルターが十分に複雑で複雑なものになると確信しています(このケースはあまり複雑ではありません)。また、私がPandasを使用しているときに "for"ループを書くと、私はそれは間違っている。

def lt_zero_ab(df): 
    result = [] 
    for index, row in df.iterrows(): 
     if row['A'] <0 and row['B'] <0: 
      result.append(index) 
    return result 
rand_df.loc[lt_zero_ab] 
4

lambdaを使用するには、列全体を渡さないでください。

rand_df.loc[lambda x: (x.A < 0) & (x.B < 0)] 
# Or 
# rand_df[lambda x: (x.A < 0) & (x.B < 0)] 

        A   B   C   D 
2017-01-12 -0.460918 -1.001184 -0.796981 0.328535 
2017-01-14 -0.146846 -1.088095 -1.055271 -0.778120 

あなたはブールnumpyのアレイ

c1 = rand_df.A.values > 0 
c2 = rand_df.B.values > 0 
rand_df[c1 & c2] 

        A   B   C   D 
2017-01-12 -0.460918 -1.001184 -0.796981 0.328535 
2017-01-14 -0.146846 -1.088095 -1.055271 -0.778120 
関連する問題