2017-07-10 2 views
1

私はPandasでチェーン割り当てを使用しないようにしています。私はこの振る舞いが私の割り当て慣行を更新しようとしているのを発見しましたが、割り当て自体に関連するとは思いません。以下の例に示すように、それはフィルタリングプロセスそのものと思われます。それはバグのようだ...しかし、おそらく私は何かを欠いている?Pandasブールインデックスエラー.drop()

df = pd.DataFrame(data = { 
         'acol' : [1.0, 3.00, 11.0, 31.0, 100.0, 314.0], 
         'bcol' : [1.0, 3.14, 10.1, 31.4, 81.2, 314.1] 
         }) 

私の古い方法でフィルタリングし、再割り当て、条件付きで一部の行を維持することであっただろう:

In[20]: df[(df.acol > df.bcol) & (df.acol > 10)] 

Out[20]: 
    acol bcol 
2 11.0 10.1 
4 100.0 81.2 

新しい、より多くの責任を私が代わりに.drop()機能を使用しようとしている...しかし、結果は矛盾しているようだ:

In[21]: df.drop((df.acol <= df.bcol) | (df.acol <= 10), axis=0) 
Out[21]: 
    acol bcol 
2 11.0 10.1 
3 31.0 31.4 
4 100.0 81.2 
5 314.0 314.1 

ド・モルガンの定理は、それらが同じ結果(https://en.wikipedia.org/wiki/De_Morgan%27s_laws)を得なければならないと言います。

ドキュメント(http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing)を確認しましたが、この動作には言及されていません。私は、データフレームのインデックス作成に多少の曖昧さがあることを認識していますが、ビット単位の演算子を使用することで、それを回避する必要があります(Pandas boolean DataFrame selection ambiguity)。

さらに、入力データの各リストから0番目のエントリを削除すると、.drop()(行2が消える)を使用したときに別の結果が得られます。

私は、Python 3.6、パンダ0.20.2

HALPを使用していますか?

答えて

2

あなたがdf.index、その後dropboolean indexingが必要になります。あなたのコードで

print (df.index[((df.acol <= df.bcol) | (df.acol <= 10))]) 
Int64Index([0, 1, 3, 5], dtype='int64') 

df1 = df.drop(df.index[((df.acol <= df.bcol) | (df.acol <= 10))]) 
print (df1) 
    acol bcol 
2 11.0 10.1 
4 100.0 81.2 

df.drop((df.acol <= df.bcol) | (df.acol <= 10)) 

はブーイングですリーンマスクは01に変換されているため、1行目と2行目は削除されました。ここでは私の意見の使用dropでそう

print ((df.acol <= df.bcol) | (df.acol <= 10)) 
0  True 
1  True 
2 False 
3  True 
4 False 
5  True 
dtype: bool 

より良いだけboolean indexing使用で、少しovercomplicatedソリューションです:query

df[(df.acol > df.bcol) & (df.acol > 10)] 

または代替ソリューションを:

df1 = df.query("acol > bcol & acol > 10") 
print (df1) 
    acol bcol 
2 11.0 10.1 
4 100.0 81.2 
+0

ユーザーに知られていない、0/1への変換を説明してくれてありがとう。私は、警告または少なくともこの点についての説明を提案するバグを提出しました。 https://github.com/pandas-dev/pandas/issues/16877 –

1

df.drop()は、ラベルまたはインデックスで動作します。あなたはboolean型マスクで、それを使用したい場合は、

df.drop(df.index[(df.acol <= df.bcol) | (df.acol <= 10)]) 

を行うことではなく、再割り当てのinplace=True引数を含めることも、より効率的です。

(これはなぜ起こるかについては、それは私の知る限りでは、単に予期しない動作です:あなたは.drop()に引数として[ True, True, False, True, False, True]を渡すことによって、同じ結果を得ることができます。)

+0

コメント@ jezraelによって私のためにこれを明らかにしました:ブール値が0または1に変換されるので、0と/またはデータフレームの最初の行は削除されますが、他の行は削除されません。たとえば、[True、True、True、True、True、True]を渡すと、最初の行は削除されますが、他の行はすべて削除されます。 私は間違いなく予期せぬ動作を見つけるので、私はパンダ開発者にバグを報告します。 –