collections.Counter()
| 対応: | Python 2(2000) |
|---|
『Counter』はリストや文字列などのイテラブルの要素の出現回数を集計する辞書のサブクラスです。頻度分析やランキング処理に使います。
構文
from collections import Counter # イテラブルから Counter を生成する c = Counter(イテラブル) # 最も多い要素をn件取得する c.most_common(n) # 全要素を出現回数分繰り返すイテレータを返す c.elements() # Counter 同士の演算 c1 + c2 # 各カウントを加算する c1 - c2 # 各カウントを減算する(0以下は除外) c1 & c2 # 各カウントの小さい方を取る c1 | c2 # 各カウントの大きい方を取る
メソッド・演算子一覧
| メソッド / 演算子 | 概要 |
|---|---|
| Counter(イテラブル) | イテラブルの要素を集計して、各要素の出現回数を値とする辞書を生成します。 |
| c.most_common(n) | 出現回数の多い順にn件を『[(要素, 回数), ...]』のリストで返します。nを省略すると全件を返します。 |
| c.elements() | 各要素を出現回数分繰り返すイテレータを返します。カウントが1未満の要素は含まれません。 |
| c.update(イテラブル) | 新しいイテラブルのカウントを既存の Counter に加算します。 |
| c.subtract(イテラブル) | 新しいイテラブルのカウントを既存の Counter から減算します。負の値も保持されます。 |
| c1 + c2 | 2つの Counter のカウントを加算した新しい Counter を返します。 |
| c1 - c2 | c1からc2のカウントを引いた Counter を返します(正の値のみ保持)。 |
サンプルコード
collections_counter.py
from collections import Counter
# リストの要素を集計する
members = ['Okabe', 'Kurisu', 'Okabe', 'Mayuri', 'Kurisu', 'Okabe']
c = Counter(members)
print(c) # Counter({'Okabe': 3, 'Kurisu': 2, 'Mayuri': 1})
# 辞書のように要素ごとのカウントにアクセスする
print(c['Okabe']) # 3
print(c['Daru']) # 存在しないキーは 0 を返す(KeyError なし)
# most_common() で頻度上位n件を取得する
print(c.most_common(2)) # [('Okabe', 3), ('Kurisu', 2)]
# 文字列の文字頻度を集計する
text = 'programming'
char_count = Counter(text)
print(char_count.most_common(3))
# 最も多い文字3件が出力される(例: [('g', 2), ('r', 2), ('m', 2)])
# update() でカウントを追加する
more_members = ['Okabe', 'Suzuha', 'Suzuha']
c.update(more_members)
print(c['Okabe']) # 4
print(c['Suzuha']) # 2
# Counter 同士の演算
c1 = Counter({'a': 3, 'b': 2})
c2 = Counter({'a': 1, 'c': 4})
print(c1 + c2) # Counter({'c': 4, 'a': 4, 'b': 2})
print(c1 - c2) # Counter({'a': 2, 'b': 2})(正の値のみ)
print(c1 & c2) # Counter({'a': 1})(小さい方)
print(c1 | c2) # Counter({'c': 4, 'a': 3, 'b': 2})(大きい方)
# elements() で要素を繰り返し展開する
print(sorted(c1.elements())) # ['a', 'a', 'a', 'b', 'b']
実行すると次のように出力されます。
python3 collections_counter.py
Counter({'Okabe': 3, 'Kurisu': 2, 'Mayuri': 1})
3
0
[('Okabe', 3), ('Kurisu', 2)]
[('r', 2), ('g', 2), ('m', 2)]
4
2
Counter({'a': 4, 'c': 4, 'b': 2})
Counter({'a': 2, 'b': 2})
Counter({'a': 1})
Counter({'c': 4, 'a': 3, 'b': 2})
['a', 'a', 'a', 'b', 'b']
よくあるミス
よくあるミス1: 存在しないキーへのアクセス
『Counter』は存在しないキーにアクセスすると『0』を返します(『KeyError』は発生しません)。この動作は通常の辞書と異なります。
from collections import Counter
c = Counter({'岡部倫太郎': 3, '牧瀬紅莉栖': 2})
# 存在しないキーは0が返る(KeyErrorにはならない)
print(c['椎名まゆり']) # 0(エラーなし)
print(c.get('椎名まゆり')) # None(getはNoneを返す)
# 辞書と異なりdelで削除してもキーが残る場合がある
del c['椎名まゆり'] # del で削除しても0が入っていたキーは消せない場合がある
よくあるミス2: most_common()の引数を忘れる
『most_common()』は引数なしで全要素を返します。上位N件だけ必要な場合は引数を指定します。
from collections import Counter
votes = Counter({'岡部倫太郎': 45, '牧瀬紅莉栖': 38, '椎名まゆり': 29,
'橋田至': 15, '阿万音鈴羽': 22})
# 引数なし: 全要素(降順)
print(votes.most_common())
# [('岡部倫太郎', 45), ('牧瀬紅莉栖', 38), ('椎名まゆり', 29), ...]
# 上位2件のみ
print(votes.most_common(2))
# [('岡部倫太郎', 45), ('牧瀬紅莉栖', 38)]
よくあるミス3: Counter同士の減算でマイナスが消える
『Counter』同士を『-』で引くと、結果が0以下の要素は自動的に削除されます。マイナスの値を保持したい場合は通常の辞書演算を使います。
from collections import Counter
before = Counter({'岡部倫太郎': 5, '牧瀬紅莉栖': 3})
after = Counter({'岡部倫太郎': 2, '牧瀬紅莉栖': 7})
# - 演算子: 0以下の要素は削除される
diff = before - after
print(diff) # Counter({'岡部倫太郎': 3})(牧瀬紅莉栖のマイナスは消える)
# subtract(): マイナスの値も保持する
result = Counter(before)
result.subtract(after)
print(dict(result)) # {'岡部倫太郎': 3, '牧瀬紅莉栖': -4}
実践パターン
テキスト分析・投票集計・在庫管理などでよく使うパターンです。
from collections import Counter
# テキストから単語頻度を集計する
text = '岡部倫太郎 牧瀬紅莉栖 岡部倫太郎 椎名まゆり 岡部倫太郎 牧瀬紅莉栖'
word_count = Counter(text.split())
print(word_count.most_common(2))
# [('岡部倫太郎', 3), ('牧瀬紅莉栖', 2)]
# 2つのCounterを合計する
morning = Counter({'岡部倫太郎': 3, '牧瀬紅莉栖': 2})
evening = Counter({'岡部倫太郎': 1, '椎名まゆり': 4})
total = morning + evening
print(dict(total))
# {'岡部倫太郎': 4, '牧瀬紅莉栖': 2, '椎名まゆり': 4}
# 差分を取る(前回からの増加分)
prev = Counter({'岡部倫太郎': 5, '牧瀬紅莉栖': 3, '橋田至': 2})
curr = Counter({'岡部倫太郎': 8, '牧瀬紅莉栖': 3, '橋田至': 4})
diff = curr - prev
print(dict(diff))
# {'岡部倫太郎': 3, '橋田至': 2}
概要
『Counter』は辞書のサブクラスなので、辞書のメソッド(『keys()』、『values()』、『items()』など)もそのまま使えます。存在しないキーを参照した場合に『KeyError』が発生せず『0』を返す点が通常の辞書と異なります。
アンケート集計・テキスト解析・ログの頻度分析など、「どの要素が何回登場するか」を調べる処理をシンプルに書けます。
Counter同士の減算(『-』演算子)は結果が0以下の要素を除外しますが、『subtract()』メソッドは負の値も保持します。用途に応じて使い分けます。
デフォルト値付き辞書は『collections.defaultdict()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。