パンダ:データフレームのインデックス作成中に複数の条件-予期しない動作


134

2つの列の値でデータフレームの行をフィルタリングしています。

何らかの理由で、OR演算子は、AND演算子の動作と同じように動作し、逆も同様です。

私のテストコード:

import pandas as pd

df = pd.DataFrame({'a': range(5), 'b': range(5) })

# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]

print pd.concat([df, df1, df2], axis=1,
                keys = [ 'original df', 'using AND (&)', 'using OR (|)',])

そしてその結果:

      original df      using AND (&)      using OR (|)    
             a  b              a   b             a   b
0            0  0              0   0             0   0
1           -1 -1            NaN NaN           NaN NaN
2            2  2              2   2             2   2
3           -1  3            NaN NaN            -1   3
4            4 -1            NaN NaN             4  -1

[5 rows x 6 columns]

ご覧のとおり、AND演算子は、少なくとも1つの値が等しいすべての行を削除します-1。一方、ORオペレーターは、両方の値が等しいこと-1を要求してそれらをドロップします。私は正反対の結果を期待します。誰かがこの動作を説明できますか?

私はパンダ0.13.1を使用しています。


1
df.queryそしてpd.eval、このユースケースのために良いフィットのように見えます。pd.eval()関数のファミリー、その機能、および使用例については、pd.eval()を使用したパンダでの動的式評価をご覧ください。
cs95 2018

回答:


210

ご覧のとおり、AND演算子は、少なくとも1つの値が-1に等しいすべての行を削除します。一方、OR演算子では、値を削除するために両方の値を-1に等しくする必要があります。

そのとおり。ドロップしたいものではなく、保持したいもので条件を記述していることに注意してください。の場合df1

df1 = df[(df.a != -1) & (df.b != -1)]

「-1ではdf.aなく、-1 ではない行を保持する」と言っています。df.bこれは、少なくとも1つの値が-1であるすべての行を削除することと同じです。

の場合df2

df2 = df[(df.a != -1) | (df.b != -1)]

あなたは「そのどちらかに行保つ言っているのdf.adf.bいないの-1」、両方の値が-1の行を落とすと同じです。

PS:のような連鎖アクセスdf['a'][1] = -1はあなたをトラブルに陥らせることができます。.locおよびを使用する習慣を身に付けることをお勧めします.iloc


24
DataFrame.query()ここでもうまく機能します。df.query('a != -1 or b != -1')
Phillip Cloud

4
なぜパンダが欲しがって&そしてそれ|以上にandしたいのかを知るために起こりorますか?
ストーブ2017年

2
通常のPythonコードでは、:@stoves andor変更することはできません基本的なPythonの意味を持っています。 &|、その一方で、彼らの行動を制御する対応する特別なメソッドがあります。(もちろん、クエリ文字列では、好きな解析を自由に適用できます。)
DSM

興味深いことに、df[True & False]失敗したように見えますがdf[(True) & (False)]成功しています(この例ではテストされていません)
ピット

この種の構文を複数行に分割することは可能でしょうか?ほとんどのPEP8は何でしょうか?
tommy.carstensen 2018

41

つまり、query()を使用できます

df_filtered = df.query('a == 4 & b != 2')

この構文の方が理にかなっていると思う状況があります。例:df.query( ''(a == 4&b!= 2)| c == 3 ")
Aus_10

9

ここで少し数学的論理理論

「NOT a AND NOT b」「NOT(a OR b)」と同じなので、次のようになります。

「a NOT -1 AND b NOT -1」「NOT(a is -1 OR b is -1)と同等であり 、これは「(a is -1 OR b is -1)」の反対(補数)です。

したがって、正反対の結果が必要な場合、df1とdf2は次のようになります。

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a == -1) | (df.b == -1)]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.