イテレータ型(リストやタプル)の要素にある2つの要素が同時に出現する回数を数えるコードです。イテレータ型の要素の組み合わせ(itertools.combination
)、イミュータブルセット(frozenset
)、キーを指定したsorted
のサンプルコードでもあります。
コード
import itertools
import typing
from itertools import chain
def count_colocation2(
iteriter: typing.Iterable
) -> typing.Dict[frozenset, int]:
"""
イテレータ型(リストやタプル)の要素にある2つの要素が同時に出現する回数を数える。
"""
if not isinstance(iteriter, typing.Iterable):
raise TypeError()
# 組み合わせを準備する
comb = itertools.combinations(frozenset(chain.from_iterable(iteriter)), 2)
comb = [frozenset(item) for item in comb]
# 順に調べて組み合わせの存在する数を加算
d = {key: 0 for key in comb}
for entry in iteriter:
for pair in comb:
t = tuple(pair)
if t[0] in entry and t[1] in entry:
d[pair] += 1
return d
from pprint import pp
from count_colocation2 import count_colocation2
ll = [
["a", "b", "c"],
["d", "e", "f"],
["a", "d", "f"],
["b", "d", "f"],
]
coloc2 = count_colocation2(ll)
# 値を降順でソート
pp(sorted(coloc2.items(), key=lambda item: item[1], reverse=True))
"""
[(frozenset({'f', 'd'}), 3),
(frozenset({'f', 'e'}), 1),
(frozenset({'f', 'b'}), 1),
(frozenset({'f', 'a'}), 1),
(frozenset({'d', 'e'}), 1),
(frozenset({'d', 'b'}), 1),
(frozenset({'d', 'a'}), 1),
(frozenset({'b', 'a'}), 1),
(frozenset({'b', 'c'}), 1),
(frozenset({'a', 'c'}), 1),
(frozenset({'f', 'c'}), 0),
(frozenset({'b', 'e'}), 0),
(frozenset({'e', 'a'}), 0),
(frozenset({'e', 'c'}), 0),
(frozenset({'d', 'c'}), 0)]
"""
備考
frozenset
frozenset
はset
のイミュータブル版です。set
はadd
やupdate
で内容を変更できますが、frozenset
は変更できません。一方、frozenset
はハッシュが取得できるので辞書のキーになれます。
# 次の行をコメント解除するとエラーが発生します。
# print(hash(set(["a", "b", "c"])))
# TypeError: unhashable type: 'set'
# 正常に完了します。
print(hash(frozenset(["a", "b", "c"])))
同じ辞書のキーとなれるイミュータブル型にtuple
があります。tuple
は要素の順番を区別しますが、frozenset
は区別しません。
typing.Sequence
、typing.Iterable
Pythonにはlist
、tuple
、set
、frozenset
のようなクラスがありますが、これらは共通の機能で分類できます。list
、tuple
はインデックスでアクセスできることからシーケンス型(typing.Sequence
)に分類されます。また、list
、tuple
、set
、frozenset
はイテレーターを提供することからtyping.Iterable
に分類されます。
typing.Sequence
とtyping.Iterable
は型として定義されており、型ヒントで使用する他、isinstance
やissubclass
でも使用できます。
イテレータ型の組み合わせタプルのリスト
itertools.combinations
によりイテレータ型(typing.Iterable
)の要素から任意の数の組み合わせタプルのリストが作成できます。
set
/frozenset
の要素へのアクセス
set
/frozenset
はインデックス[index]
ではアクセスできません。list()
やtuple()
で一度list
やtuple
に変換すればアクセスできます。イテレータ型ではあるのでfor
は使用できます。
辞書の非破壊的ソート
sorted()
のkey=...
にラムダ式を指定して辞書を非破壊的にソートできます。辞書のキーと値のペアはdict.items()
で取得することに注意してください。dict
そのものをsorted
に渡すとキー名がsorted()
の対象となります。
sorted(dict.items(), key=lambda item: item[0]) # 昇順
sorted(dict.items(), key=lambda item: item[0], reverse=True) # 降順
sorted(dict.items(), key=lambda item: item[1]) # 昇順
sorted(dict.items(), key=lambda item: item[1], reverse=True) # 降順