2017-03-20 5 views
0

タプルのキーを持つ辞書のように動作するクラスを作成しようとしていますが、このディクショナリを使用してPandasのデータフレームを作成するため、Pandasはタプルをキーとして使用するとマルチインデックス(この場合は正しくない)を意味するため、「真に」タプルとなります。カスタムタプルをキーとした辞書で、パンダのバグを迂回することはできません。

>>> a = {(1,): 1 } 
>>> pd.Series(a) 
1  NaN 
dtype: float64 

は何が起こることはパンダが辞書のキーはタプルであることを認識していることであるので、それは想定しています、単一要素のタプルの場合

が、これは例えばとして、バグを生成しますマルチインデックス。次に、タプルの lenが1であることが分かるので、結局のところプレーンなインデックスを作成することにします。しかし、辞書にはキー 1がなく、代わりに (1,)というキーがあるため、値を格納できない場合は、 NaNとなります。このバグを離れて残し

、いくつかの要素を持つ「普通の」タプルを使用して、パンダが正常に動作しますが、私はしたくないマルチレベルの指標を前提としています私が代わりに欲しい

>>> a = {(1,2): 1 } 
>>>> pd.Series(a) 
1 2 1 
dtype: int64 

が使用することですインデックスとしてタプル(1,2)

私はこの( collections標準ライブラリの UserListの実装を模倣しますが、最低限にそれを維持)のように、私自身の Tupleクラスを実装することを決定した

:私はキーとして、オブジェクトのこの種を使用する場合は

from collections.abc import Sequence 
class Tuple(Sequence): 
    def __init__(self, initlist=None): 
     self.data =() 
     if initlist is not None: 
      if type(initlist) == type(self.data): 
       self.data = initlist 
      elif isinstance(initlist, Tuple): 
       self.data = initlist.data 
      else: 
       self.data = tuple(initlist) 
    def __getitem__(self, i): return self.data[i] 
    def __len__(self): return len(self.data) 
    def __hash__(self): return hash(self.data) 
    def __repr__(self): return repr(self.data) 

Sequence.register(Tuple) 

キーはタプルであるかのよう

>>> a = {Tuple((1,2)): 1} 
>>> pd.Series(a) 
(1, 2) 1 
dtype: int64 

辞書が見えます:

私の辞書に、パンダはマルチインデックスを生成するためにそれを停止し、インデックスなどのオブジェクトを、使用することを余儀なくされます
>>> a 
{(1, 2): 1} 

これまでのところ、とても良いです。しかし、奇妙なことが起こる:

>>> a[Tuple((1,2))] 
--------------------------------------------------------------------------- 
KeyError         Traceback (most recent call last) 
<ipython-input-169-9641d6999f03> in <module>() 
----> 1 a[Tuple((1,2))] 

KeyError: (1, 2) 

なぜですか?私の知る限り、Python辞書は、Tuple.__hash__()が内部でハッシュすることによって、Tuple.__hash__()が実行する、指定されたキーのハッシュを計算することによって値を見つける必要があります。data次に、キーが見つからない理由は何ですか?

私はTupleクラスに他のいくつかのメソッドを実装する必要があると思いますが、どのクラスまたはその理由がわかりません。

+0

[ハッシュ可能](https://docs.python.org/2/glossary.html#term-hashable)に必要な比較方法のいずれかを実装しようとしましたか? – languitar

+0

@languitarはい!'__eq __()'は欠けていたメソッドでした。私は馬鹿だと感じる。ありがとうございました!あなたのコメントから答えを出したら、私はそれを受け入れます。 – JLDiaz

答えて

1

あなたはまた、hashableであることのため__eq__または__cmp__のいずれかを実装する必要があります:メソッド(それは__hash__(必要))を、その寿命の間に を変更することはありませんハッシュ値を持つ場合、オブジェクトはハッシュ可能である

、および他のオブジェクト(__eq__()または__cmp__()メソッドが必要)に比べて になる可能性があります。 等しいを比較するHashableオブジェクトは、同じハッシュ値を持つ必要があります。

関連する問題