シリーズの真理値があいまいです。a.empty、a.bool()、a.item()、a.any()またはa.all()を使用します


368

or条件付きの結果データフレームのフィルタリングに問題があります。私の結果は、0.25を超え、-0.25未満のdfすべての列のvar値を抽出する必要があります。

以下のこのロジックは、あいまいな真理値を与えますが、このフィルタリングを2つの個別の操作に分割すると機能します。ここで何が起きてるの?提案された使用する場所がわからないa.empty(), a.bool(), a.item(),a.any() or a.all()

 result = result[(result['var']>0.25) or (result['var']<-0.25)]

46
|代わりに使用or
MaxU

1
ここでは回避策があります:abs(result['var'])>0.25
ColinMac

回答:


566

Pythonの文は必要-値を。以下のためにあなたが「ビット単位」を使用する必要がありますので、これらのあいまいな考えられている(または)、または(および)の操作を:orandtruthpandas|&

result = result[(result['var']>0.25) | (result['var']<-0.25)]

これらは、これらの種類のデータ構造のためにオーバーロードされ、要素単位or(またはand)を生成します。


このステートメントに説明を追加するだけです。

あなたが取得したいときに例外がスローされたboolのをpandas.Series

>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

あなたがヒットすることは、オペレータが場所だった暗黙的にオペランドを変換しbool(あなたが使用しorますが、それはまたのために起こるandifwhile):

>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

これらの4文のほかにいくつかの隠しいくつかのPythonの関数があるbool(のような呼び出しをanyallfilter、...)これらは通常では問題ではありませんpandas.Seriesが、完全を期すために、私はこれらを言及したかったが。


あなたの場合、適切な代替案について言及していないため、例外はあまり役に立ちません。用andor(あなたは要素ごとの比較をしたい場合)は、使用することができます。

  • numpy.logical_or

    >>> import numpy as np
    >>> np.logical_or(x, y)

    または単に|演算子:

    >>> x | y
  • numpy.logical_and

    >>> np.logical_and(x, y)

    または単に&演算子:

    >>> x & y

演算子を使用している場合は、演算子の優先順位のため、括弧を正しく設定してください。

ありますいくつかの論理numpyの機能すべきで働くがpandas.Series


ifまたはの実行中に発生した場合は、例外に記載されている代替案がより適していますwhile。これらについて簡単に説明します。

  • シリーズが空かどうかを確認する場合:

    >>> x = pd.Series([])
    >>> x.empty
    True
    >>> x = pd.Series([1])
    >>> x.empty
    False

    Pythonは、通常、解釈len(のようなコンテナのGTHをlisttupleそれが明示的なブール解釈を持っていない場合、...)真理値として。あなたのpythonのようなチェックをしたいのであれば、あなたが行うことができます:if x.sizeまたはif not x.empty代わりにif x

  • ブール値Series1つだけ含まれている場合:

    >>> x = pd.Series([100])
    >>> (x > 50).bool()
    True
    >>> (x < 50).bool()
    False
  • シリーズの最初で唯一の項目をチェックしたい場合(.bool()ブール値ではないコンテンツでも機能します):

    >>> x = pd.Series([100])
    >>> x.item()
    100
  • すべてまたはいずれかのアイテムがゼロでないか、空でないか、または偽ではないかを確認する場合:

    >>> x = pd.Series([0, 1, 2])
    >>> x.all()   # because one element is zero
    False
    >>> x.any()   # because one (or more) elements are non-zero
    True

これらのpython演算子がパンダシリーズを処理するためにオーバーロードされないのはなぜですか?
Mudit Jain

@MuditJain直接オーバーロードする方法はありませんandornotPythonでは。これらの演算子boolは、オペランドの戻り値を直接使用します。そしてある意味で、Pandas / NumPy ValueErrorは、そのようなデータ構造の真偽値をあいまいと見なしているため、すでにそれを引き上げるためにオーバーロードしました。
MSeifert

解決策は大丈夫ですが、説明はあまり良いものではあり
ませ

2
@blacksheep私がもっとよく説明できることはありますか?
MSeifert

それは素晴らしい説明です。これは実際に、より抽象的な例では失敗したような方法で、ビット単位と論理を理解するのに役立ちました。
rocksNwaves

41

ブール論理の場合は&、およびを使用し|ます。

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))

>>> df
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

何が起こっているかを確認するには、比較ごとにブール値の列を取得します。たとえば、

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool

複数の基準がある場合、複数の列が返されます。これが、結合ロジックがあいまいな理由です。各列を個別に使用andまたはor処理するため、最初にその列を単一のブール値に減らす必要があります。たとえば、各列のいずれかの値またはすべての値がTrueかどうかを確認します。

# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True

# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False

同じことを達成するための複雑な方法の1つは、これらすべての列をまとめて圧縮し、適切なロジックを実行することです。

>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

詳細については、ドキュメントのブールインデックスを参照してください。


20

まあパンダはビットごとの「&」「|」を使用します 各条件は '()'でラップする必要があります

たとえば次の作品

data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]

しかし、適切な角括弧なしの同じクエリでは、

data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]

8

または、演算子モジュールを使用することもできます。詳細情報はこちらPythonドキュメント

import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C > 0.25, df.C < -0.25)]

          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.4438

1

この優れた答えは、何が起こっているかを非常によく説明し、解決策を提供します。同様の場合に適しているかもしれない別のソリューションを追加したいと思います:queryメソッドの使用:

result = result.query("(var > 0.25) or (var < -0.25)")

http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-queryもご覧ください。

(現在使用しているデータフレームを使用したいくつかのテストでは、この方法は一連のブール値でビットごとの演算子を使用するよりも少し遅い:2 ms vs 870 µs)

警告の一部:これが簡単ではない少なくとも1つの状況は、列名がたまたまpython式である場合です。私は名前の列を持っていたWT_38hph_IP_2WT_38hph_input_2log2(WT_38hph_IP_2/WT_38hph_input_2)して次のクエリを実行したいです:"(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

次の例外カスケードを取得しました。

  • KeyError: 'log2'
  • UndefinedVariableError: name 'log2' is not defined
  • ValueError: "log2" is not a supported function

これは、クエリパーサーが3番目の列の名前で式を識別するのではなく、最初の2つの列から何かを作成しようとしたために発生したと思います。

可能な回避策がここに提案されています


1

同じエラーが発生し、数日間pysparkデータフレームで停止しました。2 つのフィールドの整数値を比較していたため、na値に0を入力することで問題を解決できました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.