Python

【Python】オブジェクトを数える(カウント)する方法【Counter】

この記事では、Python でオブジェクトをカウントする方法を解説します。

オブジェクトをカウントするには辞書を使うことで実装することができますが、collectionsモジュールのCounterクラスを使うことでより簡単に実装することができます。

それでは、オブジェクトをカウントする方法を見ていきましょう。

リスト内のオブジェクトをカウント

リストに格納されているオブジェクトの個数をそれぞれ数えてみましょう。

リストに格納されている要素はcount()メソッドで数えることができます。

items = ['a', 'b', 'c', 'a', 'c', 'a']

a_count = items.count('a')
b_count = items.count('b')
c_count = items.count('c')

print(f'a: {a_count}, b: {b_count}, c: {c_count}')

実行結果

a: 3, b: 1, c: 2

しかし、上記の方法ではリストに格納されている要素が事前に判明していないと数えることができません。また、要素の種類が多い場合にcountメソッドを何度も呼び出さなければならないので効率が悪いです。

なのでcountメソッドは1つの要素が何個リストに格納されているか知りたい場合に使います。

複数、または全ての要素が何個含まれているか知りたい場合は辞書を使って実装できます。

辞書を使ってカウントする

辞書のkeyとしてオブジェクトが格納されていなければ辞書[オブジェクト] = 1で要素を追加します。すでに格納されていれば辞書[オブジェクト] += 1でカウントします。

items = ['a', 'b', 'c', 'a', 'c', 'a']
counter = {}

for item in items:
    if item in counter.keys():
        counter[item] += 1
    else:
        counter[item] = 1

print(counter)

実行結果

{'a': 3, 'b': 1, 'c': 2}

辞書を使うことでオブジェクトをカウントすることができましたがcollections.Counterクラスを使うことでもっと簡単に実装することができます。

Counterクラスを使う

collectionsモジュールのCounterクラスは、ハッシュ可能なオブジェクトをカウントしてくれる辞書のサブクラスとなっています。collectionsモジュールは、標準ライブラリなのでインポートするだけで使用可能です。

import collections

collections.Counter([iterable-or-mapping])

辞書のサブクラスなので辞書と同様の処理が可能となっています。

import collections

c = collections.Counter()
c['one'] = 1
c['two'] = 2
c['three'] = 3

c.values()
c.get('one')

初期化

要素を辞書のkey、カウントをvalueとして初期化します。シーケンスなんかは初期化しただけでカウントされます。

from collections import Counter

Counter()
# Counter()

Counter('Hello')
# Counter({'l': 2, 'H': 1, 'e': 1, 'o': 1})

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

Counter({'男': 4, '女': 2})
# Counter({'男': 4, '女': 2})

Counter(man=4, woman=2)
# Counter({'man': 4, 'woman': 2})

特徴

Counterクラス には、以下のような特徴があります。

存在しないkeyを指定してもエラーにならない

通常の辞書では存在しないkeyを指定するとKeyErrorが発生しますが、Counterクラスは、0を返します。

from collections import Counter

counter = Counter()
print(counter['存在しない要素'])

実行結果

0

要素を削除するにはdel文を使う

valueに0を指定しても要素が削除できるわけではありません。普通にdel文を使って削除しましょう!

from collections import Counter

counter = Counter('Hello')
del counter['l']
print(counter)

counter['H'] = 0
print(counter)

実行結果

Counter({'H': 1, 'e': 1, 'o': 1})
Counter({'e': 1, 'o': 1, 'H': 0})

メソッド

辞書の機能に加えて以下のメソッドが使用可能です。

element()

keyをvalueの数だけ繰り返すイテレータを返します。順序は最初に検出された順です。

from collections import Counter

counter = Counter('mogehoge')
print(list(counter.elements()))

実行結果

['m', 'o', 'o', 'g', 'g', 'e', 'e', 'h']

most_common([n])

(key, value)のタプルを格納したリストを取得できます。並びはカウント数が多いものから格納されています。カウントが同じ場合は、検出された順で格納されます。

from collections import Counter

counter = Counter('mogehoge')
print(counter.most_common())

実行結果

[('o', 2), ('g', 2), ('e', 2), ('m', 1), ('h', 1)]

n引数を指定することで取得するタプルの数を指定できます。

from collections import Counter

counter = Counter('mogehoge')
print(counter.most_common(3))

実行結果

[('o', 2), ('g', 2), ('e', 2)]

subtract([iterable-or-mapping])

引数に指定したイテラブル、または辞書の要素だけカウントが引かれます。

from collections import Counter

# イテラブルオブジェクトの場合
counter = Counter('mogehoge')
counter.subtract('moge')

print(counter)

# 辞書の場合
counter = Counter('mogehoge')
counter.subtract({'m': 3, 'o': 2})

print(counter)

実行結果

Counter({'o': 1, 'g': 1, 'e': 1, 'h': 1, 'm': 0})
Counter({'g': 2, 'e': 2, 'h': 1, 'o': 0, 'm': -2})

まとめ

この記事では、オブジェクトをカウントする方法を解説しました。

オブジェクトをカウントするには辞書を使うことで実装できましたがcollections.Counterクラスを使うことでより簡単にカウントできました。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ