私はパンダでブールインデックスを使用しています。問題は、声明がなぜであるかです:
a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]
正常に動作しますが
a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]
エラーで終了しますか?
例:
a=pd.DataFrame({'x':[1,1],'y':[10,20]})
In: a[(a['x']==1)&(a['y']==10)]
Out: x y
0 1 10
In: a[(a['x']==1) and (a['y']==10)]
Out: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
あなたが言う時
(a['x']==1) and (a['y']==10)
(a['x']==1)
および(a['y']==10)
をブール値に変換するようにPythonに暗黙的に要求しています。
NumPy配列(長さが1を超える)およびSeriesなどのPandasオブジェクトにはブール値がありません。つまり、
ValueError: The truth value of an array is ambiguous. Use a.empty, a.any() or a.all().
ブール値として使用される場合。それは、その TrueまたはFalseになるべきかどうか不明 であるためです。一部のユーザーは、Pythonリストのように、長さがゼロではない場合にTrueと想定する場合があります。他の人は、allの要素がTrueである場合にのみTrueにしたいかもしれません。他の人は、その要素のanyがTrueであればTrueにしたいかもしれません。
相反する期待が非常に多いため、NumPyとPandasの設計者は推測することを拒否し、代わりにValueErrorを発生させます。
代わりに、empty()
、all()
またはany()
メソッドを呼び出して、希望する動作を示すことにより、明示的にする必要があります。
ただし、この場合、ブール値の評価は不要であり、element-wiselogical-andが必要です。それが&
二項演算子が実行することです:
(a['x']==1) & (a['y']==10)
ブール配列を返します。
ところで、 alexpmil notes のように、&
には==
よりも高い 演算子優先順位 があるため、括弧は必須です。括弧がなければ、a['x']==1 & a['y']==10
はa['x'] == (1 & a['y']) == 10
として評価され、連鎖比較(a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10)
と同等になります。これは、Series and Series
という形式の式です。 2つのシリーズでand
を使用すると、上記と同じValueError
が再びトリガーされます。そのため、括弧は必須です。
&
、|
、~
であり、括弧(...)
は重要です!Pythonのand
、or
、およびnot
論理演算子は、スカラーで動作するように設計されています。したがって、Pandasは、この機能のベクトル化(要素単位)バージョンを実現するために、ビット単位演算子をオーバーライドする必要があります。
python(exp1
とexp2
の以下はブール値の結果に評価される式です)...
exp1 and exp2 # Logical AND
exp1 or exp2 # Logical OR
not exp1 # Logical NOT
...に変換されます...
exp1 & exp2 # Element-wise logical AND
exp1 | exp2 # Element-wise logical OR
~exp1 # Element-wise logical NOT
パンダ用。
論理演算の実行中にValueError
を取得する場合、グループ化に括弧を使用する必要があります。
(exp1) op (exp2)
例えば、
(df['col1'] == x) & (df['col2'] == y)
等々。
Boolean Indexing :一般的な操作は、論理条件を通じてブールマスクを計算してデータをフィルタリングすることです。Pandas提供three演算子:論理ANDの&
、論理ORの|
、および論理NOTの~
。
次の設定を検討してください。
np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df
A B C
0 5 0 3
1 3 7 9
2 3 5 2
3 4 7 6
4 8 8 1
上記のdf
について、A <5およびB> 5のすべての行を返したいとします。これは、各条件のマスクを個別に計算し、それらをAND演算することによって行われます。
ビットごとのオーバーロード&
演算子
続行する前に、このドキュメントの特定の抜粋に注意してください。
もう1つの一般的な操作は、ブールベクトルを使用してデータをフィルタリングすることです。演算子は、
or
の場合は|
、and
の場合は&
、not
の場合は~
です。 これらは、デフォルトでPythonがdf.A > 2 & df.B < 3
などの式をdf.A > (2 & df.B) < 3
として評価するため、括弧を使用してグループ化する必要があります。順序は(df.A > 2) & (df.B < 3)
です。
したがって、これを念頭に置いて、要素ごとの論理ANDは、ビットごとの演算子&
を使用して実装できます。
df['A'] < 5
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'] > 5
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
(df['A'] < 5) & (df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
そして、その後のフィルタリング手順は単純に、
df[(df['A'] < 5) & (df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
括弧は、条件演算子<
および>
よりも優先順位が高いビット単位演算子のデフォルトの優先順位をオーバーライドするために使用されます。 pythonドキュメントの Operator Precedence のセクションを参照してください。
括弧を使用しない場合、式は誤って評価されます。たとえば、次のような何かを誤って試みた場合
df['A'] < 5 & df['B'] > 5
次のように解析されます
df['A'] < (5 & df['B']) > 5
どちらになる
df['A'] < something_you_dont_want > 5
これは( チェーン演算子比較 )のpythonドキュメントを参照)、
(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)
どちらになる
# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2
どっちが
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
だから、その間違いをしないでください!1
括弧のグループ化の回避
修正は実際には非常に簡単です。ほとんどの演算子には、DataFrameに対応するバインドメソッドがあります。条件演算子ではなく関数を使用して個々のマスクを構築する場合、評価順序を指定するために括弧でグループ化する必要はなくなります。
df['A'].lt(5)
0 True
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'].gt(5)
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
df['A'].lt(5) & df['B'].gt(5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
柔軟な比較のセクションを参照してください。 。要約すると、
╒════╤════════════╤════════════╕
│ │ Operator │ Function │
╞════╪════════════╪════════════╡
│ 0 │ > │ gt │
├────┼────────────┼────────────┤
│ 1 │ >= │ ge │
├────┼────────────┼────────────┤
│ 2 │ < │ lt │
├────┼────────────┼────────────┤
│ 3 │ <= │ le │
├────┼────────────┼────────────┤
│ 4 │ == │ eq │
├────┼────────────┼────────────┤
│ 5 │ != │ ne │
╘════╧════════════╧════════════╛
括弧を避けるための別のオプションは、 DataFrame.query
(またはeval
)を使用することです:
df.query('A < 5 and B > 5')
A B C
1 3 7 9
3 4 7 6
私はを広範に持っています_。にquery
とeval
を文書化しています ダイナミック式評価pandasでpd.eval() を使用しています。
operator.and_
この操作を機能的な方法で実行できます。内部的にビット単位演算子に対応するSeries.__and__
を呼び出します。
import operator
operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
df[operator.and_(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
通常これは必要ありませんが、知っておくと便利です。
一般化: np.logical_and
(およびlogical_and.reduce
)
別の方法として、np.logical_and
を使用する方法があります。これも、括弧のグループ化を必要としません。
np.logical_and(df['A'] < 5, df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
Name: A, dtype: bool
df[np.logical_and(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
np.logical_and
は func(Universal Functions) であり、ほとんどのufuncには reduce
メソッドがあります。これは、ANDに複数のマスクがある場合、logical_and
で一般化するのが簡単であることを意味します。たとえば、m1
とm2
とm3
を&
と組み合わせて、あなたがしなければならない
m1 & m2 & m3
ただし、より簡単なオプションは
np.logical_and.reduce([m1, m2, m3])
これは、より複雑なロジック(たとえば、リスト内包表記でマスクを動的に生成し、それらすべてを追加する)を使用して構築できるため、強力です。
import operator
cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]
m = np.logical_and.reduce([op(df[c], v) for op, c, v in Zip(ops, cols, values)])
m
# array([False, True, False, True, False])
df[m]
A B C
1 3 7 9
3 4 7 6
1-私はこの点について心配していることは知っていますが、どうか我慢してください。これは非常に、非常に一般的な初心者の間違いであり、非常に徹底的に説明する必要があります。
上記のdf
について、A == 3またはB == 7であるすべての行を返したいとします。
ビットごとのオーバーロード|
df['A'] == 3
0 False
1 True
2 True
3 False
4 False
Name: A, dtype: bool
df['B'] == 7
0 False
1 True
2 False
3 True
4 False
Name: B, dtype: bool
(df['A'] == 3) | (df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[(df['A'] == 3) | (df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
まだお持ちでない場合は、上記の論理ANDのセクションもお読みください。すべての警告がここに適用されます。
または、この操作は次のように指定できます。
df[df['A'].eq(3) | df['B'].eq(7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
operator.or_
内部でSeries.__or__
を呼び出します。
operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[operator.or_(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
np.logical_or
2つの条件では、logical_or
を使用します。
np.logical_or(df['A'] == 3, df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df[np.logical_or(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
複数のマスクの場合、logical_or.reduce
を使用します。
np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False, True, True, True, False])
df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
次のようなマスクを指定します
mask = pd.Series([True, True, False])
すべてのブール値を反転する必要がある場合(最終結果が[False, False, True]
になるように)、以下のいずれかの方法を使用できます。
ビット単位~
~mask
0 False
1 False
2 True
dtype: bool
繰り返しますが、式は括弧で囲む必要があります。
~(df['A'] == 3)
0 True
1 False
2 False
3 True
4 True
Name: A, dtype: bool
これは内部的に呼び出します
mask.__invert__()
0 False
1 False
2 True
dtype: bool
ただし、直接使用しないでください。
operator.inv
シリーズで__invert__
を内部的に呼び出します。
operator.inv(mask)
0 False
1 False
2 True
dtype: bool
np.logical_not
これはnumpyの亜種です。
np.logical_not(mask)
0 False
1 False
2 True
dtype: bool
np.logical_and
は、np.bitwise_and
、logical_or
をbitwise_or
、logical_not
をinvert
に置き換えることができます。
パンダのブールインデックスの論理演算子
pandas.Series
またはpandas.DataFrame
sでPython論理演算子(and
、or
またはnot
)のいずれも使用できないことを認識することが重要です(同様に使用できません)複数の要素を持つnumpy.array
s)。これらを使用できない理由は、これらのデータ構造が配列のブール値が曖昧であると判断したため、例外で例外をスローするオペランドでbool
を暗黙的に呼び出すためです。
>>> import numpy as np
>>> import pandas as pd
>>> arr = np.array([1,2,3])
>>> s = pd.Series([1,2,3])
>>> df = pd.DataFrame([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> bool(df)
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
私はこれをより広範囲にカバーしました 「シリーズの真理値はあいまいです。a.empty、a.bool()、a.item()、a.any()またはa.allを使用してください。 () "Q + A 。
ただし、 NumPy は、これらの演算子と同等の要素単位の操作を、numpy.array
、pandas.Series
、pandas.DataFrame
、またはその他の(準拠する)numpy.array
サブクラスで使用できる関数として提供します。
and
には np.logical_and
がありますor
には np.logical_or
がありますnot
には np.logical_not
がありますnumpy.logical_xor
同等のPythonはありませんが、論理的です "exclusive or" 操作したがって、本質的には、df1
とdf2
がpandas DataFramesであると仮定して使用する必要があります。
np.logical_and(df1, df2)
np.logical_or(df1, df2)
np.logical_not(df1)
np.logical_xor(df1, df2)
ただし、ブールNumPy配列、pandasシリーズ、またはpandas DataFramesがある場合は、 要素ごとのビット単位関数 (ブール値の場合は-または少なくとも論理関数と見分けがつかない):
np.bitwise_and
または&
演算子np.bitwise_or
または|
演算子np.invert
(またはエイリアスnp.bitwise_not
)または~
演算子np.bitwise_xor
または^
演算子通常、演算子が使用されます。ただし、比較演算子と組み合わせた場合、ビット単位演算子には 比較演算子よりも高い優先順位 があるため、比較を括弧で囲む必要があります。
(df1 < 10) | (df2 > 10) # instead of the wrong df1 < 10 | df2 > 10
Python論理演算子は比較演算子より優先順位が低いため、通常はa < 10 and b > 10
(ここでa
とb
は単純な整数です)を記述し、括弧を必要としないため、これはいらいらするかもしれません。
ビット演算と論理演算は、ブール値のNumPy配列(およびブール値のシリーズとデータフレーム)でのみ同等であることを強調することは本当に重要です。これらにブール値が含まれていない場合、操作によって異なる結果が得られます。 NumPy配列を使用した例を含めますが、結果はpandasデータ構造についても同様です。
>>> import numpy as np
>>> a1 = np.array([0, 0, 1, 1])
>>> a2 = np.array([0, 1, 0, 1])
>>> np.logical_and(a1, a2)
array([False, False, False, True])
>>> np.bitwise_and(a1, a2)
array([0, 0, 0, 1], dtype=int32)
また、NumPy(および同様にパンダ)はブール( ブールまたは「マスク」インデックス配列 )と整数( インデックス配列 )インデックスに対して異なることを行うため、インデックス作成の結果も異なる:
>>> a3 = np.array([1, 2, 3, 4])
>>> a3[np.logical_and(a1, a2)]
array([4])
>>> a3[np.bitwise_and(a1, a2)]
array([1, 1, 1, 2])
Logical operator | NumPy logical function | NumPy bitwise function | Bitwise operator
-------------------------------------------------------------------------------------
and | np.logical_and | np.bitwise_and | &
-------------------------------------------------------------------------------------
or | np.logical_or | np.bitwise_or | |
-------------------------------------------------------------------------------------
| np.logical_xor | np.bitwise_xor | ^
-------------------------------------------------------------------------------------
not | np.logical_not | np.invert | ~
NumPy配列、pandas Series、およびpandas DataFramesでは論理演算子は機能しません。その他は、これらのデータ構造(およびプレーンPythonオブジェクト)で機能し、要素ごとに機能します。ただし、プレーンPython bool
sのビット単位の反転には注意してください。ブールはこのコンテキストでは整数として解釈されます(たとえば、~False
は-1
を返し、~True
は-2
を返します)。