collectionsモジュールのCounterクラスを使って、文字列やリストにどんな要素が何個含まれているかを簡単にカウントする方法を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
from collections import Counter
# 反復可能オブジェクトの要素を数え上げる
c = Counter('deep insider')
print(c)
# 出力結果
#Counter({'e': 3, 'd': 2, 'i': 2, 'p': 1, ' ': 1, 'n': 1, 's': 1, 'r': 1})
print(c['d']) # 2
print(c['D']) # 0:含まれていなかった要素のカウントは0
l = ['foo', 'foo', 'bar', 'baz', 'baz', 'foo']
c = Counter(l)
print(c) # Counter({'foo': 3, 'baz': 2, 'bar': 1})
# 一番たくさんある要素をmost_commonメソッドで調べる
l = ['foo', 'foo', 'bar', 'baz', 'baz', 'foo']
c = Counter(l)
mx = c.most_common()
print(mx) # [('foo', 3), ('baz', 2), ('bar', 1)]
mx = c.most_common(2) # 多い順にn個を取り出す
print(mx) # [('foo', 3), ('baz', 2)]
for k, v in mx:
print(f'item: {k}, occurrence: {v}')
# 出力結果:
#item: foo, occurrence: 3
#item: baz, occurrence: 2
Pythonに標準で付属するcollectionsモジュールにはCounterクラスが含まれている。このクラスは文字列やリストなどの反復可能なオブジェクトの要素を数え上げるのに使用できる。また、その要素をキーとする辞書の形で情報を格納するため、数え上げる対象はハッシュ可能なオブジェクトとなる(Counterクラスはdictクラスの派生クラスである)。
簡単な例を以下に示す。
from collections import Counter
c = Counter('deep insider')
print(c)
# 出力結果
#Counter({'e': 3, 'd': 2, 'i': 2, 'p': 1, ' ': 1, 'n': 1, 's': 1, 'r': 1})
これは反復可能オブジェクトとして文字列'deep insider'を指定してCounterクラスのインスタンスを作成する例だ。これにより、この文字列を構成する文字を数え上げて、その結果に辞書と同様な形でアクセスできるようになる。例えば、'd'という文字がこの文字列に何文字含まれているかを知るには、以下のように角かっこ「[]」に'd'を指定する。
print(c['d']) # 2
辞書と異なるのは、含まれていない要素を指定した場合に例外を発生しない点だ。例えば、辞書であれば、それに含まれていないキーを指定すると以下のように例外が発生する。
d = dict(c) # 上で作成したカウンターを基に辞書を作成
print(d) # {'d': 2, 'e': 3, 'p': 1, ' ': 1, 'i': 2, 'n': 1, 's': 1, 'r': 1}
print(d['D']) # KeyError
一方、Counterクラスのインスタンスは存在しない要素のカウント結果を知るために、存在しないキーを指定すると、次のように0を返す。
print(c['D']) # 0:含まれていなかった要素のカウントは0
文字列を構成する要素(文字)の数え上げという点では、Counterクラスは個々の文字が何文字含まれているかを知るのには役立つが、文字列に部分文字列が何個含まれているか(例えば、'deeeep insider'に'ee'が何個含まれているか)を知るといった処理を行うのであれば、「文字列のcountメソッドで特定の部分文字列が含まれている数を数えるには」で紹介している文字列のcountメソッドを使うことになるだろう。
リストに含まれている要素の数え上げも同様に行える。
l = ['foo', 'foo', 'bar', 'baz', 'baz', 'foo']
c = Counter(l)
print(c) # Counter({'foo': 3, 'baz': 2, 'bar': 1})
この例では反復可能オブジェクトとしてリストを指定してCounterクラスのインスタンスを指定している。このときには、リストにどんな要素が何個含まれているかがカウントされる。リストには'foo'が3つ、'bar'が1つ、'baz'が2つ含まれているので、上に示す結果になっている。
また、このクラスにはmost_commonインスタンスメソッドがあり、これを呼び出すと、インスタンス作成時に指定された反復可能オブジェクトに含まれている要素とその数をタプルにまとめたものを要素とするリストが返される。
以下に例を示す。リストには先と同じ要素が含まれている。
l = ['foo', 'foo', 'bar', 'baz', 'baz', 'foo']
c = Counter(l)
mx = c.most_common()
print(mx) # [('foo', 3), ('baz', 2), ('bar', 1)]
most_commonメソッドには数の多い要素を先頭から何個取り出すかを指定できる。以下は数の多い順に要素を2つ取り出す例だ。
mx = c.most_common(2) # 多い順に2個を取り出す
print(mx) # [('foo', 3), ('baz', 2)]
得られるのはタプルを要素とするリストなので、以下のように反復処理も可能だ。
for k, v in mx:
print(f'item: {k}, occurrence: {v}')
# 出力結果:
#item: foo, occurrence: 3
#item: baz, occurrence: 2
なお、Counterクラスは辞書の派生クラスでもあるので、キー(要素)と値(数)の組を組み合わせて処理するだけであれば、次のように書いてもよい(most_commonメソッドの戻り値ではなく、Counterクラスのインスタンスに対してitemsメソッドを呼び出している点に注意)。
for k, v in c.items():
print(f'item: {k}, occurrence: {v}')
# 出力結果:
#item: foo, occurrence: 3
#item: bar, occurrence: 1
#item: baz, occurrence: 2
このときには要素の多い順ではなく、Counterクラスのインスタンス生成時に要素が挿入された順となる点には注意しよう。
Copyright© Digital Advantage Corp. All Rights Reserved.