web-dev-qa-db-ja.com

pandas論理式とifステートメントを使用したシリーズ値の評価

Ifステートメントを使用して辞書の値を評価するのに問題があります。

データフレームからインポートした次のディクショナリを考えます(重要な場合)。

>>> pnl[company]
29:   Active Credit       Date   Debit Strike Type
0      1      0 2013-01-08  2.3265  21.15  Put
1      0      0 2012-11-26      40     80  Put
2      0      0 2012-11-26     400     80  Put

次の文を評価して、Activeの最後の値の値を確立しようとしました。

if pnl[company].tail(1)['Active']==1:
    print 'yay'

ただし、次のエラーメッセージが表示されました。

Traceback (most recent call last):
  File "<pyshell#69>", line 1, in <module>
    if pnl[company].tail(1)['Active']==1:
  File "/usr/lib/python2.7/dist-packages/pandas/core/generic.py", line 676, in __nonzero__
    .format(self.__class__.__name__))
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Ifステートメントなしで上記のコマンドを使用して必要な値を表示できることを考えると、これは私を驚かせました:

>>> pnl[company].tail(1)['Active']
30: 2    0
Name: Active, dtype: object

値が明らかに0で、インデックスが2であることを考えると、簡単な健全性チェックのために次のことを試してみたところ、予期したとおりに事態が発生していないことがわかりました。

>>> if pnl[company]['Active'][2]==0:
...     print 'woo-hoo'
... else:
...     print 'doh'


doh

私の質問は:

1)ここで何が起こっているのでしょうか?基本的なレベルで辞書を誤解しているのではないかと思います。

2)この辞書の特定の値を表示すると、左側の数値が1ずつ増加することに気付きました。これは何を表していますか?例えば:

>>> pnl[company].tail(1)['Active']
31: 2    0
Name: Active, dtype: object
>>> pnl[company].tail(1)['Active']
32: 2    0
Name: Active, dtype: object
>>> pnl[company].tail(1)['Active']
33: 2    0
Name: Active, dtype: object
>>> pnl[company].tail(1)['Active']
34: 2    0
Name: Active, dtype: object

助けてくれてありがとう。

13
neanderslob

生成されるのはPandas Seriesオブジェクトであり、これは、行を次のように変更する必要がある単一の値であっても、試行している方法では評価できません。

_if pnl[company].tail(1)['Active'].any()==1:
  print 'yay'
_

2番目の質問に関しては、私のコメントをご覧ください。

[〜#〜] edit [〜#〜]

コメントと出力へのリンクから、any()を呼び出すとエラーメッセージが修正されますが、データは実際には文字列であるため、比較はまだ失敗します。

_if pnl[company].tail(1)['Active'].any()=='1':
  print 'yay'
_

文字列比較を行う、または読み取りまたは生成されたデータを修正する。

または行う:

_pnl['Company']['Active'] = pnl['Company']['Active'].astype(int)
_

比較がより正確になるように、列のdtypeを変換します。

6
EdChum

シリーズはNDFrameのサブクラスです。 _NDFrame.__bool___メソッド 常にValueErrorを発生させます 。したがって、ブール値のコンテキストでSeriesを評価しようとすると、ValueErrorが発生します-Seriesの値が1つしかなくてもです。

NDFrameがブール値を持たない(つまり、常にValueErrorを発生させる)理由は、NDFrameがTrueであると合理的に期待できる基準が複数あるためです。意味するかもしれない

  1. nDFrameのすべてのアイテムがTrueであるか、そうである場合(.all()を使用)
  2. nDFrameのすべてのアイテムがTrueであるか、そうであれば(Series.any()を使用します)
  3. nDFrameは空ではありません(空の場合、.empty()を使用します)

どちらかが可能であり、ユーザーごとに異なる期待があるため、開発者は推測することを拒否し、NDFrameのユーザーに使用する基準を明示するよう要求します。

エラーメッセージには、最も可能性の高い選択肢がリストされています。

A.empty、a.bool()、a.item()、a.any()、またはa.all()を使用します

あなたの場合、シリーズには値が1つだけ含まれることがわかっているので、itemを使用できます。

_if pnl[company].tail(1)['Active'].item() == 1:
    print 'yay'
_

2番目の質問について:左側の数字は、Pythonインタープリター(PyShell?)によって生成された行番号付けのようです。しかし、それは単なる推測です。


警告:おそらく、

_if pnl[company].tail(1)['Active']==1:
_

seriesの単一の値が1に等しい場合に条件をTrueにしたいことを意味します。コード

_if pnl[company].tail(1)['Active'].any()==1:
    print 'yay'
_

seriesのdtypeが数値で、Seriesの値が0以外のanynumberである場合、Trueになります。たとえば、pnl[company].tail(1)['Active']と等しい

_In [128]: s = pd.Series([2], index=[2])
_

それから

_In [129]: s.any()
Out[129]: True
_

したがって、

_In [130]: s.any()==1
Out[130]: True
_

s.item() == 1は、意図した意味をより忠実に保持すると思います。

_In [132]: s.item()==1
Out[132]: False
_

_(s == 1).any()_も機能しますが、anyを使用しても、Seriesに含まれる値は1つだけであることがわかっているため、意図をあまり明確に表現していません。

3
unutbu

あなたの質問は、Python辞書、またはネイティブPythonまったく。それは、pandasシリーズ、他の答えはあなたに正しい構文を与えました:

あなたの質問をより広い意味で解釈すると、それは_pandas Series_がNumPyにどのようにシューホーンされたのか、そして NumPyは最近まで論理値と演算子のサポートが悪名が悪かった についてです。 pandasはNumPyが提供するもので最高の仕事をします。任意の(Python)演算子でコードを書く代わりにnumpy論理関数を時々手動で呼び出さなければならないのは面倒で不格好で、時には肥大化しますpandasコード。また、パフォーマンスのためにこれを頻繁に行う必要があります(ネイティブPythonとの間でサンクするよりも優れた数値)。しかし、それが代償です。

多くの制限、癖、落とし穴があります(以下の例)-最良のアドバイスは、pandas numpyの制限のため、第一級市民としてのブール値に不信であることです:

_import numpy as np
import pandas as pd
s = pd.Series([True, True, False, True, np.NaN])
s2  = pd.Series([True, True, False, True, np.NaN])
dir(s) # look at .all, .any, .bool, .eq, .equals, .invert, .isnull, .value_counts() ...

s.astype(bool) # WRONG: should use the member s.bool ; no parentheses, it's a member, not a function
# 0     True
# 1     True
# 2    False
# 3     True
# 4     True  # <--- should be NA!!
#dtype: bool

s.bool
# <bound method Series.bool of
# 0     True
# 1     True
# 2    False
# 3     True
# 4      NaN
# dtype: object>

# Limitation: value_counts() currently excludes NAs
s.value_counts()
# True     3
# False    1
# dtype: int64
help(s.value_counts) # "... Excludes NA values(!)"

# Equality comparison - vector - fails on NAs, again there's no NA-handling option):
s == s2 # or equivalently, s.eq(s2)
# 0     True
# 1     True
# 2     True
# 3     True
# 4    False  # BUG/LIMITATION: we should be able to choose NA==NA
# dtype: bool

# ...but the scalar equality comparison says they are equal!!
s.equals(s2)
# True
_
0
smci