Python Counter:collections.Counterで要素を数える
Updated on
リスト内の要素、文字列内の文字、ドキュメント内の単語の出現回数を数えることは、プログラミングで最も一般的なタスクの1つです。手動で行うと、ループを書き、辞書を初期化し、条件分岐や.get()呼び出しで欠損キーを処理する必要があります。このボイラープレートコードは実際の意図を不明瞭にし、バグを生み、頻度カウントが必要になるたびに作業を遅くします。
Pythonのcollections.Counterはこの摩擦を完全に排除します。1行でハッシュ可能なオブジェクトをカウントし、最も一般的な要素を見つけるための組み込みメソッドを提供し、頻度分布を比較するための算術演算をサポートします。このガイドでは、基本的なカウントから高度なマルチセット演算まで、Counterを効果的に使用するために必要なすべてをカバーします。
collections.Counterとは?
CounterはPythonのcollectionsモジュールにある辞書のサブクラスで、ハッシュ可能なオブジェクトのカウントに特化して設計されています。各要素は辞書のキーとして格納され、そのカウントが対応する値として格納されます。
from collections import Counter
fruits = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
count = Counter(fruits)
print(count)
# Counter({'apple': 3, 'banana': 2, 'cherry': 1})Counterの作成
Counterは複数の入力タイプを受け入れるため、さまざまなデータソースに対して柔軟です。
from collections import Counter
# リストから
colors = Counter(['red', 'blue', 'red', 'green', 'blue', 'red'])
print(colors) # Counter({'red': 3, 'blue': 2, 'green': 1})
# 文字列から(各文字をカウント)
letters = Counter('mississippi')
print(letters) # Counter({'s': 4, 'i': 4, 'p': 2, 'm': 1})
# 辞書から
inventory = Counter({'apples': 15, 'oranges': 10, 'bananas': 7})
# キーワード引数から
stock = Counter(laptops=5, monitors=12, keyboards=30)カウントへのアクセス
基本的なインデックス
通常の辞書のようにカウントにアクセスできますが、欠損キーはKeyErrorを発生させる代わりに0を返します:
from collections import Counter
c = Counter(['a', 'b', 'a'])
print(c['a']) # 2
print(c['z']) # 0 (KeyErrorなし!)
# 通常のdictの動作と比較
d = {'a': 2, 'b': 1}
# d['z'] # KeyErrorが発生するこのゼロデフォルトの動作により、多くのカウントシナリオで.get(key, 0)やdefaultdict(int)が不要になります。
すべての要素を取得
elements()メソッドは要素に対するイテレータを返し、各要素をそのカウント回数だけ繰り返します:
from collections import Counter
c = Counter(a=3, b=2, c=1)
print(list(c.elements()))
# ['a', 'a', 'a', 'b', 'b', 'c']most_common()メソッド
most_common()メソッドは頻度順にソートされた要素を返します。
from collections import Counter
text = "to be or not to be that is the question"
word_freq = Counter(text.split())
# すべての要素を頻度順にソート
print(word_freq.most_common())
# [('to', 2), ('be', 2), ('or', 1), ('not', 1), ...]
# 上位N要素のみ
log_levels = Counter(['INFO', 'WARNING', 'INFO', 'ERROR', 'INFO', 'DEBUG',
'WARNING', 'INFO', 'ERROR', 'INFO'])
print(log_levels.most_common(2))
# [('INFO', 5), ('WARNING', 2)]
# 最も少ない(逆スライス)
print(log_levels.most_common()[-2:])
# [('DEBUG', 1), ('ERROR', 2)]Counterの算術演算
Counterは頻度分布の結合と比較のための算術演算と集合演算をサポートします。
from collections import Counter
morning = Counter(coffee=10, tea=5, juice=3)
afternoon = Counter(coffee=8, tea=7, water=4)
# 加算:カウントを結合
total = morning + afternoon
print(total) # Counter({'coffee': 18, 'tea': 12, 'water': 4, 'juice': 3})
# 減算:正のカウントのみ保持
stock = Counter(apples=20, oranges=15, bananas=10)
sold = Counter(apples=8, oranges=15, bananas=12)
remaining = stock - sold
print(remaining) # Counter({'apples': 12})
# 積集合(&):対応するカウントの最小値
a = Counter(apple=3, banana=2, cherry=5)
b = Counter(apple=1, banana=4, cherry=2)
print(a & b) # Counter({'cherry': 2, 'banana': 2, 'apple': 1})
# 和集合(|):対応するカウントの最大値
print(a | b) # Counter({'cherry': 5, 'banana': 4, 'apple': 3})
# 単項+:ゼロおよび負のカウントを除去
c = Counter(a=3, b=0, c=-2)
print(+c) # Counter({'a': 3})更新と減算
from collections import Counter
# update()はカウントを加算(dict.updateは置換するが、こちらは加算)
c = Counter(a=3, b=1)
c.update(['a', 'b', 'b', 'c'])
print(c) # Counter({'a': 4, 'b': 3, 'c': 1})
# subtract()はカウントを減算(ゼロと負を保持)
c = Counter(a=4, b=2, c=0)
c.subtract(Counter(a=1, b=3, c=2))
print(c) # Counter({'a': 3, 'b': -1, 'c': -2})
# total()はすべてのカウントの合計を返す(Python 3.10+)
inventory = Counter(widgets=50, gadgets=30, gizmos=20)
print(inventory.total()) # 100実用的なユースケース
単語頻度分析
from collections import Counter
import re
text = """
Python is a versatile programming language. Python is used for web development,
data science, machine learning, and automation. Python's simplicity makes it
a favorite among developers.
"""
words = re.findall(r'\b[a-z]+\b', text.lower())
word_freq = Counter(words)
print("Top 5 most frequent words:")
for word, count in word_freq.most_common(5):
print(f" {word}: {count}")アナグラム検出
from collections import Counter
def are_anagrams(word1, word2):
return Counter(word1.lower()) == Counter(word2.lower())
print(are_anagrams("listen", "silent")) # True
print(are_anagrams("hello", "world")) # False投票集計システム
from collections import Counter
votes = ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob', 'Alice',
'Charlie', 'Alice', 'Bob', 'Alice']
results = Counter(votes)
winner, winning_votes = results.most_common(1)[0]
total_votes = sum(results.values())
print(f"Election Results (Total votes: {total_votes}):")
for candidate, count in results.most_common():
percentage = (count / total_votes) * 100
print(f" {candidate}: {count} votes ({percentage:.1f}%)")
print(f"\nWinner: {winner} with {winning_votes} votes")ログファイル分析
from collections import Counter
import re
log_entries = [
"2026-02-10 08:15:00 ERROR Database connection failed",
"2026-02-10 08:15:01 INFO Retrying connection",
"2026-02-10 08:15:02 ERROR Database connection failed",
"2026-02-10 08:16:00 WARNING Disk usage at 85%",
"2026-02-10 08:17:00 INFO Request processed",
"2026-02-10 08:18:00 ERROR API timeout",
]
levels = Counter(
re.search(r'(INFO|WARNING|ERROR)', line).group()
for line in log_entries
)
print("Log Level Distribution:")
for level, count in levels.most_common():
print(f" {level}: {count}")Counter vs defaultdict(int):使い分け
| 特徴 | Counter | defaultdict(int) |
|---|---|---|
| 目的 | カウント専用に構築 | 汎用のデフォルト辞書 |
| 初期化 | Counter(iterable)で一度にカウント | 手動ループが必要 |
| 欠損キー | 0を返す | 0を返す |
most_common() | 組み込みメソッド | 手動でソートが必要 |
算術(+、-) | サポート | 非サポート |
集合演算(&、|) | サポート | 非サポート |
elements() | 展開されたイテレータを返す | 利用不可 |
update()の動作 | カウントに加算 | 値を置換 |
| パフォーマンス | 最適化されたC実装 | やや遅い |
| 最適な用途 | 頻度分析、マルチセット操作 | カスタムデフォルト値ロジック |
Counterを使用:要素のカウントや頻度分布の比較が主な目的の場合。defaultdict(int)を使用:カウントがより広いデータ構造パターンの付随的な部分の場合。
頻度分布の可視化
Counterで要素をカウントした後、分布を可視化したくなることがよくあります。頻度分布のインタラクティブな探索には、PyGWalker (opens in a new tab)がpandas DataFrameをJupyter内で直接TableauスタイルのインタラクティブUIに変換します:
from collections import Counter
import pandas as pd
import pygwalker as pyg
# CounterをDataFrameに変換
data = Counter("abracadabra")
df = pd.DataFrame(data.items(), columns=['Character', 'Count'])
# インタラクティブな可視化を起動
walker = pyg.walk(df)これは大きなカウンタがあり、頻度分布をインタラクティブにフィルタリング、ソート、探索したい場合に特に便利です。
FAQ
collections.CounterはPythonで何をする?
collections.Counterはハッシュ可能なオブジェクトをカウントする辞書のサブクラスです。任意のイテラブルを渡すと、キーが要素で値がそのカウントである辞書のようなオブジェクトを返します。頻度分析のためのmost_common()などのメソッド、カウントを結合するための算術演算子を提供し、KeyErrorを発生させる代わりに欠損キーにゼロを返します。
Python Counterを使ってリスト内のアイテムの出現回数を数えるには?
collectionsからCounterをインポートしてリストを直接渡します:Counter(['a', 'b', 'a', 'c'])はCounter({'a': 2, 'b': 1, 'c': 1})を返します。特定のカウントを取得するには要素でインデックスします:counter['a']は2を返します。最も頻繁な要素にはcounter.most_common(n)を使用します。
カウントにおけるCounterと通常の辞書の違いは?
Counterはカウント専用に構築されています:イテラブル全体を1回の呼び出しでカウントし、KeyErrorの代わりに欠損キーに0を返し、ソートされた頻度のためのmost_common()があり、算術演算(+、-、&、|)をサポートし、値を置き換えるのではなくカウントに加算するupdate()を含みます。通常の辞書は手動のループ構築が必要で、これらの機能がありません。
2つのCounterオブジェクトを減算または加算できる?
はい。+演算子はカウントを結合します:Counter(a=3) + Counter(a=1)はCounter({'a': 4})を生成します。-演算子はカウントを減算し、ゼロまたは負の結果を破棄します。&演算子は対応するカウントの最小値(積集合)、|は最大値(和集合)を与えます。負のカウントを保持する減算には、代わりにsubtract()メソッドを使用します。
Python Counterは大規模データセットに対して効率的?
はい。CounterはCPythonで最適化されたCコードで実装されており、カウントにおいて手動のPythonループより高速です。イテラブルからのCounterの作成はO(n)です。個々のカウントへのアクセスはO(1)です。most_common(k)操作は内部的にヒープを使用し、top-k要素のみが必要な場合にO(n log k)の効率を実現します。
まとめ
Pythonのcollections.Counterは要素のカウントと頻度分析のための標準ツールです。手動の辞書カウントを単一のコンストラクタ呼び出しに置き換え、即座のランキングのためにmost_common()を提供し、マルチセット比較を簡単にする算術演算をサポートします。単語頻度の分析、投票の集計、在庫管理、ログファイルの分析など、Counterがカウントを処理するので、あなたは重要なロジックに集中できます。