集合型で2次元リスト中の重複した行を削除する
データセットの中でユニークなデータをカウントしたい時があります。
重複を含んだリストの場合、 一度集合型(set型)に変換することで重複を排除することができます。
In [1]: lst = [0, 1, 0, 3, 2, 1, 1]
In [2]: set(lst)
Out[2]: {0, 1, 2, 3}
しかし、2次元配列にこの方法を適用しようとすると、
In [1]: arr = [[0,1,0], [1,1,0], [0,0,1], [0,1,0], [1,1,1], [1,1,0]]
In [2]: set(arr)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-1e4050a05c36> in <module>()
----> 1 set(arr)
TypeError: unhashable type: 'list'
と怒られます。これは、 リストがhashableでない ことが原因です。
hashableなオブジェクトは、
- 代入後の変更が不可能
- 他のオブジェクトと比較できる
という特徴を持ちます。 リストは代入後の変更が可能であるため、hashableではないと言えます。
辞書型と集合型は内部でハッシュ値を使っているため、 辞書のキーや集合のメンバにはhashableなオブジェクトしかなれません。 後者の例の場合、1次元のリストを集合型のメンバにしようとしたためエラーが出たのです。
解決方法
ざっくり言うと、リストがダメなら hashableなオブジェクトに変換してしまえば良い ということです。
各行をタプルに変換します。 タプルはhashableなので、集合型を使ってユニークなデータを抽出できます。
In [1]: arr = [[0,1,0], [1,1,0], [0,0,1], [0,1,0], [1,1,1], [1,1,0]]
In [2]: set(map(tuple, arr))
Out[2]: {(1, 1, 0), (0, 1, 0), (0, 0, 1), (1, 1, 1)}