結論から言うと、collections はリストや辞書を使った処理を、より書きやすくするための標準ライブラリです。

Pythonでは、データを数えたり、種類ごとにまとめたりする処理をよく書きます。
通常の辞書でも実現できますが、毎回初期値を確認するコードが増えると、本当にやりたい処理が見えにくくなることがあります。
この記事では、注文データを集計する例を使って、Counterdefaultdict の基本を整理します。

この記事でわかること

  • Counter で件数を数える方法
  • defaultdict でデータをグループ分けする方法
  • 実務の集計処理で使うときの注意点

完成コード

完成コードは次の通りです。

from collections import Counter, defaultdict


orders = [
    {"customer": "田中", "category": "文具", "amount": 1200},
    {"customer": "佐藤", "category": "食品", "amount": 2500},
    {"customer": "田中", "category": "文具", "amount": 800},
    {"customer": "鈴木", "category": "食品", "amount": 1500},
    {"customer": "佐藤", "category": "書籍", "amount": 3000},
]


def count_by_category(items: list[dict[str, object]]) -> Counter[str]:
    return Counter(str(item["category"]) for item in items)


def group_amounts_by_customer(items: list[dict[str, object]]) -> dict[str, list[int]]:
    grouped: defaultdict[str, list[int]] = defaultdict(list)
    for item in items:
        customer = str(item["customer"])
        amount = int(item["amount"])
        grouped[customer].append(amount)
    return dict(grouped)


category_counts = count_by_category(orders)
amounts_by_customer = group_amounts_by_customer(orders)

print("カテゴリ別件数")
for category, count in category_counts.most_common():
    print(f"{category}: {count}件")

print("顧客別金額")
for customer, amounts in amounts_by_customer.items():
    print(f"{customer}: 合計{sum(amounts)}円")

このコードを実行すると、カテゴリ別の注文件数と、顧客別の注文金額合計を表示します。

コードのポイント

このコードでは、注文データの集計に Counterdefaultdict を使っています。

  • Counter でカテゴリごとの件数を数えています
  • most_common() で件数が多い順に取り出しています
  • defaultdict(list) で顧客ごとの金額リストを作っています
  • キーが初めて出てきたときの初期化処理を書かずに済んでいます
  • 最後に通常の dict に変換して返しています

collections は特別なことをするためだけのライブラリではありません。
よくあるデータ処理を、読みやすく短く書くために使える道具です。

コードを順番に説明します

主要な処理を分けて説明します。

1. Counterで件数を数えます

def count_by_category(items: list[dict[str, object]]) -> Counter[str]:
    return Counter(str(item["category"]) for item in items)

Counter は、同じ値が何回出てきたかを数えるためのクラスです。
ここでは、注文データから category を取り出し、カテゴリごとの件数を数えています。

通常の辞書で書く場合は、キーがあるかどうかを確認してから数を増やす必要があります。
Counter を使うと、その部分を短く書けます。

2. most_commonで多い順に取り出します

for category, count in category_counts.most_common():
    print(f"{category}: {count}件")

most_common() は、件数が多い順に結果を返します。
集計結果をレポートとして表示したい場合に便利です。

上位3件だけ見たい場合は、category_counts.most_common(3) のように数を指定できます。
アクセスログやアンケート結果のように、よく出る値を確認したいときにも使えます。

3. defaultdictでグループ分けします

grouped: defaultdict[str, list[int]] = defaultdict(list)
for item in items:
    customer = str(item["customer"])
    amount = int(item["amount"])
    grouped[customer].append(amount)

defaultdict(list) は、まだ存在しないキーにアクセスしたとき、自動で空のリストを用意します。
そのため、grouped[customer].append(amount) とそのまま書けます。

通常の辞書で同じことをする場合、キーがなければ空リストを作る処理が必要です。
defaultdict を使うと、グループ分けの本筋だけを書きやすくなります。

4. 通常のdictに戻して返します

return dict(grouped)

defaultdict は辞書のように使えますが、戻り値として外へ渡すときは通常の dict に変換することがあります。
そのほうが、呼び出し側が特別な初期値の動きを意識しなくて済みます。

関数の中では defaultdict を使って処理を簡単にし、外へ返すときは普通の辞書にする、という使い方は実務でも扱いやすい形です。

実務で使うときのポイント

実務では、collections はログ集計、注文集計、アンケート結果、ファイル種別の集計などで役立ちます。
特に、同じ値を数えるなら Counter、キーごとにリストへまとめるなら defaultdict(list) が使いやすいです。

ただし、便利だからといって何でも collections に寄せる必要はありません。
単純な辞書で十分に読みやすい処理なら、そのままでも問題ありません。
初期化処理や集計処理が増えて読みにくくなったときに、Counterdefaultdict を選ぶと効果が分かりやすいです。

第3章で扱ったCSV読み込みと組み合わせると、ファイルから読んだデータを集計できます。
第6章の標準ライブラリを組み合わせていくと、外部ライブラリなしでも小さな業務集計ツールを作れるようになります。

よくある勘違い・注意点

  • Counter は件数を数える用途に向いていますが、複雑な集計には別の設計が必要になることがあります
  • defaultdict は便利ですが、存在しないキーにアクセスすると値が作られる点に注意します
  • 外へ返す値は、必要に応じて通常の dict に変換すると扱いやすくなります
  • すべての辞書処理を collections に置き換える必要はありません

まとめ

  • collections は、データ処理を読みやすくするための標準ライブラリです
  • Counter を使うと、同じ値の出現回数を簡単に数えられます
  • defaultdict(list) を使うと、キーごとのグループ分けを書きやすくできます
  • 実務では、ログ、注文、アンケート、CSVデータの集計で役立ちます

次の記事