Python Counter.most_common()とは?多い順に取り出す方法

PythonのCounter.most_common()は、出現回数が多い順に要素を取り出すメソッドです。

「一番よく出る単語は?」「アクセスの多いページTOP5は?」といったランキング処理が1行で書けます。


most_common()の基本的な使い方

from collections import Counter

c = Counter("abracadabra")

print(c)
print(c.most_common(3))

実行結果:

Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
[('a', 5), ('b', 2), ('r', 2)]

引数に渡した件数だけ、多い順に返ります。中身は(要素, 回数)のタプルです。


引数を省略すると全件返る

from collections import Counter

c = Counter("abracadabra")
print(c.most_common())

実行結果:

[('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]

全要素が多い順に並びます。「ランキングをすべて表示したい」ときは引数なしで呼びます。


リストの集計に使う

実務でいちばん多い使い方です。

from collections import Counter

votes = ["佐藤", "鈴木", "佐藤", "高橋", "佐藤", "鈴木"]
c = Counter(votes)

print(c)
print(c.most_common(1))

実行結果:

Counter({'佐藤': 3, '鈴木': 2, '高橋': 1})
[('佐藤', 3)]

戻り値はリストである点に注意してください。1位だけが欲しくても、そのままでは使えません。

name, n = c.most_common(1)[0]
print(name, n)

実行結果:

佐藤 3

[0]でリストから1件目のタプルを取り出し、アンパックして名前と回数に分けています。


戻り値の型を確認する

from collections import Counter

c = Counter(["佐藤", "鈴木", "佐藤"])
r = c.most_common(2)

print(type(r), type(r[0]))

実行結果:

<class 'list'> <class 'tuple'>

辞書ではなくリストなので、r["佐藤"]のようなアクセスはできません。辞書が欲しいときはdict(c.most_common(3))と変換します。


同じ回数のときはどう並ぶか

from collections import Counter

c = Counter(["b", "a", "c", "a", "b"])

print(c)
print(c.most_common())

実行結果:

Counter({'b': 2, 'a': 2, 'c': 1})
[('b', 2), ('a', 2), ('c', 1)]

aとbはどちらも2回ですが、bが先に来ています。回数が同じ要素は、最初に現れた順で並びます(アルファベット順ではありません)。

並び順を自分で決めたいときはsorted()を使います。

print(sorted(c.most_common(), key=lambda x: (-x[1], x[0])))

実行結果:

[('a', 2), ('b', 2), ('c', 1)]

回数の降順、同数なら要素名の昇順になりました。


少ない順・最下位を取り出す

most_common()に「少ない順」のオプションはありません。並びを反転させます。

from collections import Counter

c = Counter(["佐藤", "鈴木", "佐藤", "高橋", "佐藤", "鈴木"])

print("少ない順:", c.most_common()[::-1])
print("最下位2件:", c.most_common()[:-3:-1])

実行結果:

少ない順: [('高橋', 1), ('鈴木', 2), ('佐藤', 3)]
最下位2件: [('高橋', 1), ('鈴木', 2)]

[:-3:-1]は「末尾から2件」という意味です。読みにくければc.most_common()[::-1][:2]でも構いません。


件数より大きい数を渡したとき

from collections import Counter

c = Counter(["佐藤", "鈴木", "佐藤", "高橋", "佐藤", "鈴木"])
print(c.most_common(99))

実行結果:

[('佐藤', 3), ('鈴木', 2), ('高橋', 1)]

エラーにはならず、あるだけ返ります。件数が足りるか事前に確認する必要はありません。


単語の出現ランキングを作る

from collections import Counter

text = "python is easy python is fun python is powerful"
wc = Counter(text.split())

for w, n in wc.most_common(3):
    print(f"{w}: {n}")

実行結果:

python: 3
is: 3
easy: 1

for w, n in ...と書くと、タプルがそのまま2つの変数に展開されます。アクセスログのURL集計、アンケートの自由記述の頻出語抽出などに、そのまま応用できます。


「最も多い1件」だけが必要なら、統計の最頻値を求める関数もあります。「Python statistics.mode()とは?最頻値を求める方法」を参照してください。

辞書から直接ランキングを作る

すでに集計済みの辞書があるなら、Counter()に渡すだけです。

from collections import Counter

d = {"りんご": 5, "みかん": 12, "ぶどう": 3}
print(Counter(d).most_common())

実行結果:

[('みかん', 12), ('りんご', 5), ('ぶどう', 3)]

sorted()と比べてどうか

同じことはsorted()でも書けます。

print(sorted(c.items(), key=lambda x: x[1], reverse=True))

結果は同じですが、most_common(n)には2つの利点があります。

  • 読みやすい:意図が名前で表現されている
  • 上位n件なら速い:全体を並べ替えず、内部でheapqを使う

要素1,000種・10万件のデータで上位3件を取る処理を1,000回繰り返すと、手元の環境ではmost_common(3)が0.057秒、sorted()が0.090秒でした(環境により変わります)。件数を指定するならmost_common()を選んでください。


most_common()のまとめ

  • most_common(n)は多い順にn件を返す
  • 戻り値は(要素, 回数)のタプルのリスト。辞書ではない
  • 引数を省略すると全件返る
  • 1位だけ欲しいときはmost_common(1)[0]
  • 同数は最初に現れた順。名前順にしたいならsorted()で並べ直す
  • 少ない順は[::-1]で反転させる
  • 要素数より大きいnを渡してもエラーにならない

あわせて読みたい

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら