【Python】collectionsモジュールの使い方を初心者向けに徹底解説!Counter・defaultdictで集計を簡単に

Counter・defaultdictの使い方を徹底解説

※このサイトの記事内では広告を掲載している場合があります。

「リストの中に同じ値が何回出てくるか数えたい」「辞書でカウントしようとしたら KeyError が出てしまった」――Pythonを学び始めると、こんな場面に一度は出会いますよね。私も現場でログやCSVを集計するとき、最初は if 文だらけの長いコードを書いていました。

実はこうした「数える」「グループ分けする」処理は、Python標準ライブラリの collectionsモジュール を使うと驚くほどシンプルに書けます。この記事では、特に使用頻度の高い Counterdefaultdict の使い方を、初心者の方にも分かるように実行結果つきで解説します。

collectionsモジュールとは?

collectionsは、Pythonに最初から入っている標準ライブラリで、リストや辞書をさらに便利にした「特殊なデータ型」がまとめられています。インストールは不要で、import するだけで使えます。

  • Counter:要素の出現回数を数える辞書
  • defaultdict:存在しないキーにも初期値を自動で用意してくれる辞書
  • その他:deque(両端キュー)、namedtuple(名前付きタプル)、OrderedDict など

どちらも辞書の仲間なので、辞書の基本を押さえておくと理解がスムーズです。不安な方は先に 辞書(dict)の使い方を解説した記事 を読んでおくのがおすすめです。

Counterの基本的な使い方

辞書で数える場合との比較

まずはCounterを使わずに、普通の辞書で果物の個数を数えてみます。

fruits = ["apple", "banana", "apple", "orange", "banana", "apple"]

counts = {}
for f in fruits:
    if f in counts:
        counts[f] += 1
    else:
        counts[f] = 1

print(counts)
# 実行結果: {'apple': 3, 'banana': 2, 'orange': 1}

キーがあるかどうかで分岐が必要なので、少し長くなってしまいます。これをCounterで書くと、たった1行です。

Counterで出現回数を数える

from collections import Counter

fruits = ["apple", "banana", "apple", "orange", "banana", "apple"]
c = Counter(fruits)

print(c)
# 実行結果: Counter({'apple': 3, 'banana': 2, 'orange': 1})

print(c["apple"])
# 実行結果: 3

print(c["grape"])  # 存在しないキー
# 実行結果: 0

ポイントは、存在しないキーを指定しても KeyError にならず 0 が返る ことです。通常の辞書ではエラーになるので、この違いは覚えておきましょう。なお、1つの値だけを数えたいならリストの count() でも十分です。count() については count関数の使い方を解説した記事 で詳しく紹介しています。

ちなみに、こうした「標準ライブラリで楽に書く」発想は、独学だとなかなか気づけないポイントでもあります。独学で伸び悩んでいると感じたら、現役SEの視点でまとめた プログラミングを学びたい人におすすめのスクール5選 も参考にしてみてください。無料体験で「質問できる環境」を試してみるだけでも、学習効率が大きく変わりますよ。

most_common()でランキングを作る

Counterの一番便利なメソッドが most_common() です。出現回数の多い順に (要素, 回数) のタプルのリストを返してくれます。

print(c.most_common(2))
# 実行結果: [('apple', 3), ('banana', 2)]

引数を省略すると、すべての要素を多い順に返します。自分で並び替える方法が気になる方は sortとsortedの違いを解説した記事 もあわせてどうぞ。

文字列や単語を数える

Counterにはリストだけでなく、文字列も渡せます。文字列を渡すと1文字ずつ数えてくれます。

from collections import Counter

# 文字ごとに数える
print(Counter("hello world").most_common(3))
# 実行結果: [('l', 3), ('o', 2), ('h', 1)]

# 単語ごとに数える(split()でリストにしてから渡す)
sentence = "python is fun and python is easy"
print(Counter(sentence.split()).most_common(2))
# 実行結果: [('python', 2), ('is', 2)]

update()と足し算・引き算

Counter同士は足し算・引き算ができ、update()で後から要素を追加することもできます。引き算で0以下になった要素は自動的に消えます。

from collections import Counter

c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)

print(c1 + c2)
# 実行結果: Counter({'a': 4, 'b': 3})

print(c1 - c2)
# 実行結果: Counter({'a': 2})

c1.update(["b", "c"])
print(c1)
# 実行結果: Counter({'a': 3, 'b': 2, 'c': 1})

合計数を知りたいときは sum(c.values()) と書けばOKです。

defaultdictの基本的な使い方

通常の辞書で起きるKeyError

通常の辞書では、存在しないキーに対していきなり += 1 をするとエラーになります。

d = {}
d["x"] += 1
# 実行結果: KeyError: 'x'

defaultdict(int)で自動的に0から始める

defaultdictは、作成時に「初期値を作る関数」を渡しておくと、存在しないキーにアクセスしたときに自動でその初期値を用意してくれます。int を渡すと初期値は 0 になります。

from collections import defaultdict

dd = defaultdict(int)
dd["x"] += 1

print(dd)
# 実行結果: defaultdict(<class 'int'>, {'x': 1})

print(dict(dd))  # 普通の辞書に変換
# 実行結果: {'x': 1}

defaultdict(list)でグループ分けする

実務で特に便利なのが list を渡すパターンです。「クラスごとに生徒をまとめる」といったグループ分けが簡単に書けます。

from collections import defaultdict

students = [("A組", "田中"), ("B組", "佐藤"), ("A組", "鈴木"),
            ("B組", "高橋"), ("C組", "伊藤")]

groups = defaultdict(list)
for cls, name in students:
    groups[cls].append(name)

print(dict(groups))
# 実行結果: {'A組': ['田中', '鈴木'], 'B組': ['佐藤', '高橋'], 'C組': ['伊藤']}

通常の辞書なら「キーがなければ空のリストを作る」という分岐が必要ですが、defaultdictならその処理が不要になります。

注意点:参照しただけでキーが作られる

defaultdictは「存在しないキーを参照しただけ」でもキーが追加されてしまいます。存在チェックをしたいときは in を使いましょう。

from collections import defaultdict

d2 = defaultdict(int)
print(d2["y"])
# 実行結果: 0

print(len(d2))  # 参照しただけで "y" が追加されている
# 実行結果: 1

print("z" in d2, len(d2))  # in ならキーは増えない
# 実行結果: False 1

実践例:ログのレベル別件数を集計する

最後に、私が現場でもよく使う「ログの集計」をCounterで書いてみます。f文字列と組み合わせると、見やすいレポートがすぐに作れます。

from collections import Counter

logs = ["ERROR", "INFO", "WARN", "INFO", "ERROR", "INFO"]

for level, n in Counter(logs).most_common():
    print(f"{level}: {n}件")

# 実行結果:
# INFO: 3件
# ERROR: 2件
# WARN: 1件

リストを作る段階で条件を絞りたい場合は、リスト内包表記 と組み合わせると、さらにスッキリ書けます。

Counterとdefaultdictの使い分け

  • 出現回数を数えたい・ランキングを出したい → Counter
  • キーごとにリストや合計をまとめたい → defaultdict(list) / defaultdict(int)
  • 1つの値の個数だけ知りたい → リストの count() で十分

もっと効率的にPythonを学びたい人へ

collectionsのような便利な標準ライブラリは、知っているかどうかでコードの量も品質も大きく変わります。ただ、独学だと「そもそもこういう書き方がある」と気づくのが難しいのも事実です。

「未経験からPythonを確実に身につけたい」「分からないところをすぐ質問したい」という方は、マンツーマン指導のスクールを検討してみるのも一つの手です。講師に直接質問できるので、つまずいた箇所をその場で解消でき、転職を見据えたサポートも受けられます。まずは無料カウンセリングで、自分に合うか確かめてみてください。

※本記事には広告(アフィリエイトリンク)を含みます。

Pythonプログラミング|マンツーマンレッスンで初めてをプロに育てる【Python Winner】

スクール選びで迷っている方は、おすすめのプログラミングスクール比較記事 で選び方のポイントもチェックしてみてください。

まとめ

  • collectionsはインストール不要の標準ライブラリで、from collections import Counter, defaultdict で使える
  • Counterは要素の出現回数を1行で数えられ、存在しないキーは 0 を返す
  • most_common(n) で出現回数ランキングを簡単に作れる
  • Counter同士は足し算・引き算、update()での追加ができる
  • defaultdict(int) でカウント、defaultdict(list) でグループ分けが KeyError なしで書ける
  • defaultdictは参照しただけでキーが追加されるので、存在チェックは in を使う

「数える」「まとめる」処理はデータ分析でも業務システムでも頻繁に登場します。ぜひ手を動かして、Counterとdefaultdictを使いこなしてみてください!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA