Pythonで文字・文字列の出現回数をカウント

Modified: | Tags: Python, 文字列, 正規表現

Pythonで、文字列strに含まれる特定の文字・文字列の出現回数(個数)をカウントする方法について説明する。

テキストファイルを文字列として読み込む方法は以下の記事を参照。

文字列全体の長さ(文字数)を取得する方法や、漢字・ひらがな・カタカナ・英数字を抽出してカウントする方法、文字列を検索してその位置などを取得する方法については以下の記事を参照。

文字・文字列の出現回数(個数)をカウント: count()

文字列strcount()メソッドで指定した文字列が何個含まれているかをカウントできる。

当然ながら、文字(長さ1の文字列)のカウントも可能。

s = 'abc_aabbcc_abc'
print(s.count('abc'))
# 2

print(s.count('a'))
# 4

print(s.count('xyz'))
# 0
source: str_count.py

第2引数start、第3引数endで範囲の指定も可能。スライス[start:end]の範囲が対象となる。

print(s.count('a', 4, 10))
# 2

print(s[4:10])
# aabbcc

print(s[4:10].count('a'))
# 2
source: str_count.py

スライスと同様、負の値を指定すると後ろからの位置になる。また、第3引数endを省略すると末尾までが範囲となる。

print(s.count('a', -9))
# 2

print(s[-9:])
# abbcc_abc

print(s[-9:].count('a'))
# 2
source: str_count.py

count()では同じ文字が重複してカウントされることはない。

s = 'abc_abc_abc'
print(s.count('abc_abc'))
# 1
source: str_count.py

重複してカウントしたい場合は、後述の正規表現を使う。

単語数をカウント

文字列のcount()メソッドでは、例えば"am"をカウントしたい場合に"Sam"もカウントされてしまう。

s = 'I am Sam'
print(s.count('am'))
# 2
source: str_count.py

単語としてカウントしたい場合、split()メソッドで単語ごとのリストに変換する方法がある。リストにもcount()メソッドがあり、値が完全に一致した要素のみがカウントされる。

l = s.split()
print(l)
# ['I', 'am', 'Sam']

print(l.count('am'))
# 1
source: str_count.py

長い文章の場合、Python標準ライブラリcollectionsのCounterクラスを使うと各単語の出現回数などが簡単にカウントできるので便利。以下の記事を参照。

なお、split()で単語に分割するのは最もシンプルな方法。実際の文章は様々な記号が含まれていたりするので、厳密に分割するにはNLTKなどの自然言語処理ライブラリを利用するのが安全。

日本語の文章を分かち書きするにはJanomeが便利。

正規表現でカウント: re.findall()

正規表現パターンにマッチした部分文字列をカウントするにはre.findall()を使う。

re.findall()は、マッチするすべての部分を文字列のリストとして返す。その要素数(組み込み関数len()で取得)がマッチした部分の数となる。

import re

s = '123-456-789'
print(re.findall('[0-9]{3}', s))
# ['123', '456', '789']

print(len(re.findall('[0-9]{3}', s)))
# 3
source: str_count.py

上の例の[0-9]{3}は3桁の数字(0~9)にマッチする正規表現パターン。

また、先読みアサーション(?=...)および丸括弧(...)によるグルーピングを用いると重複してカウントすることも可能。

s = 'abc_abc_abc'
print(re.findall('(?=(abc_abc))', s))
# ['abc_abc', 'abc_abc']

print(len(re.findall('(?=(abc_abc))', s)))
# 2

s = '12345'
print(re.findall('(?=([0-9]{3}))', s))
# ['123', '234', '345']

print(len(re.findall('(?=([0-9]{3}))', s)))
# 3
source: str_count.py

Pythonの正規表現モジュールreについての詳細は以下の記事を参照。

大文字・小文字を区別せずにカウント

count()は大文字・小文字を区別して処理する。

s = 'abc_ABC'
print(s.count('abc'))
# 1
source: str_count.py

大文字・小文字を区別せずにカウントしたい場合は、大文字または小文字に変換して統一すればよい。文字列をすべて大文字に変換するにはupper()、小文字に変換するにはlower()を使う。

print(s.lower())
# abc_abc

print(s.lower().count('abc'))
# 2

print(s.upper())
# ABC_ABC

print(s.upper().count('ABC'))
# 2
source: str_count.py

正規表現の場合、re.findall()などの関数の引数flagsre.IGNORECASEを指定すると、大文字・小文字を区別せずにカウントできる。

print(re.findall('abc', s, flags=re.IGNORECASE))
# ['abc', 'ABC']

print(re.findall('ABC', s, flags=re.IGNORECASE))
# ['abc', 'ABC']
source: str_count.py

関連カテゴリー

関連記事