Pythonで文字・文字列の出現回数をカウントする方法:countとCounter完全ガイド

フリーランスボード

20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード

ITプロパートナーズ

週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ

Midworks 10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks

count()メソッドによる基本的なカウント

文字列の出現回数

text = "apple banana apple orange apple"
apple_count = text.count("apple")
print(apple_count)  # 3

# 大文字小文字を区別
text = "Hello hello HELLO"
hello_count = text.count("hello")
print(hello_count)  # 1(小文字のみ)

文字の出現回数

text = "Hello, World!"
l_count = text.count("l")
print(l_count)  # 3

# 複数文字もカウント可能
comma_space_count = text.count(", ")
print(comma_space_count)  # 1

範囲を指定したカウント

text = "apple banana apple orange apple"
# 10文字目から25文字目までの範囲でカウント
partial_count = text.count("apple", 10, 25)
print(partial_count)  # 1

Counterクラスによる高度なカウント

基本的な使い方

from collections import Counter

text = "Hello, World!"
char_counter = Counter(text)
print(char_counter)
# Counter({'l': 3, 'o': 2, 'H': 1, 'e': 1, ',': 1, ' ': 1, 'W': 1, 'r': 1, 'd': 1, '!': 1})

単語の出現回数

from collections import Counter

text = "apple banana apple orange apple banana"
words = text.split()
word_counter = Counter(words)
print(word_counter)
# Counter({'apple': 3, 'banana': 2, 'orange': 1})

最頻出要素の取得

from collections import Counter

text = "Python is great and Python is fun"
words = text.lower().split()
word_counter = Counter(words)

# 最も多い上位2つ
most_common = word_counter.most_common(2)
print(most_common)  # [('python', 2), ('is', 2)]

実用的な活用例

テキストファイルの文字頻度解析

from collections import Counter
import re

def analyze_text_frequency(text):
    """テキストの文字・単語頻度を解析"""
    # 文字頻度(アルファベットのみ)
    chars = re.findall(r'[a-zA-Z]', text.lower())
    char_freq = Counter(chars)
    
    # 単語頻度
    words = re.findall(r'\b\w+\b', text.lower())
    word_freq = Counter(words)
    
    return char_freq, word_freq

text = "Python is a powerful programming language. Python is easy to learn."
char_freq, word_freq = analyze_text_frequency(text)

print("文字頻度:", char_freq.most_common(5))
print("単語頻度:", word_freq.most_common(5))

ログファイルのエラー集計

from collections import Counter
import re

def analyze_log_errors(log_content):
    """ログファイルのエラーレベル別集計"""
    # エラーレベルを抽出
    error_levels = re.findall(r'\b(ERROR|WARN|INFO|DEBUG)\b', log_content)
    level_counter = Counter(error_levels)
    
    return level_counter

log_sample = """
2024-08-06 10:30:15 INFO Application started
2024-08-06 10:31:20 ERROR Database connection failed
2024-08-06 10:32:10 WARN Memory usage high
2024-08-06 10:33:05 ERROR Authentication error
2024-08-06 10:34:00 INFO Process completed
"""

error_stats = analyze_log_errors(log_sample)
print(error_stats)  # Counter({'ERROR': 2, 'INFO': 2, 'WARN': 1})

アクセスログの解析

from collections import Counter
import re

def analyze_access_log(log_lines):
    """アクセスログのIP・ステータスコード集計"""
    ip_counter = Counter()
    status_counter = Counter()
    
    for line in log_lines:
        # IPアドレスを抽出(行頭の部分)
        ip_match = re.match(r'^(\d+\.\d+\.\d+\.\d+)', line)
        if ip_match:
            ip_counter[ip_match.group(1)] += 1
        
        # ステータスコードを抽出
        status_match = re.search(r'" (\d{3}) ', line)
        if status_match:
            status_counter[status_match.group(1)] += 1
    
    return ip_counter, status_counter

log_lines = [
    '192.168.1.1 - - [06/Aug/2024:10:30:00 +0900] "GET /index.html HTTP/1.1" 200 1234',
    '192.168.1.2 - - [06/Aug/2024:10:30:05 +0900] "GET /about.html HTTP/1.1" 404 567',
    '192.168.1.1 - - [06/Aug/2024:10:30:10 +0900] "POST /login HTTP/1.1" 200 890'
]

ip_stats, status_stats = analyze_access_log(log_lines)
print("IP別アクセス:", ip_stats)
print("ステータス別:", status_stats)

日本語テキストの解析

ひらがな・カタカナ・漢字の分析

from collections import Counter
import re

def analyze_japanese_text(text):
    """日本語テキストの文字種別分析"""
    hiragana = re.findall(r'[あ-ん]', text)
    katakana = re.findall(r'[ア-ン]', text)
    kanji = re.findall(r'[一-龯]', text)
    
    return {
        'ひらがな': Counter(hiragana),
        'カタカナ': Counter(katakana),
        '漢字': Counter(kanji)
    }

japanese_text = "私はPythonプログラミングを学習しています。とても楽しいです。"
analysis = analyze_japanese_text(japanese_text)

for char_type, counter in analysis.items():
    if counter:
        print(f"{char_type}: {counter.most_common(3)}")

文の長さ分布

from collections import Counter
import re

def analyze_sentence_length(text):
    """文の長さ分布を分析"""
    # 文で分割(。で区切る)
    sentences = re.split(r'[。!?]', text)
    sentences = [s.strip() for s in sentences if s.strip()]
    
    # 各文の長さをカウント
    lengths = [len(sentence) for sentence in sentences]
    length_counter = Counter(lengths)
    
    return length_counter, sentences

text = "これは短い文です。これはもう少し長い文になります。これは非常に長い文で、多くの単語を含んでいます。"
length_dist, sentences = analyze_sentence_length(text)

print("文の長さ分布:", length_dist)
for i, sentence in enumerate(sentences):
    print(f"文{i+1} ({len(sentence)}文字): {sentence}")

複数ファイルの統計処理

ディレクトリ内ファイルの拡張子集計

from collections import Counter
import os

def count_file_extensions(directory):
    """ディレクトリ内のファイル拡張子を集計"""
    extension_counter = Counter()
    
    for filename in os.listdir(directory):
        if os.path.isfile(os.path.join(directory, filename)):
            _, ext = os.path.splitext(filename)
            if ext:  # 拡張子がある場合のみ
                extension_counter[ext.lower()] += 1
            else:
                extension_counter['拡張子なし'] += 1
    
    return extension_counter

# 使用例(実際のディレクトリパスに変更してください)
# ext_stats = count_file_extensions('.')
# print(ext_stats)

カスタムカウント関数

重複を無視したユニーク要素のカウント

def count_unique_subsequences(text, length=2):
    """指定長の部分文字列をユニークカウント"""
    from collections import Counter
    
    substrings =  for i in range(len(text)-length+1)]
    return Counter(substrings)

text = "abcabc"
bigram_count = count_unique_subsequences(text, 2)
print(bigram_count)  # Counter({'ab': 2, 'bc': 2, 'ca': 1})

条件付きカウント

from collections import Counter

def conditional_count(text, condition):
    """条件を満たす文字のみカウント"""
    filtered_chars = [char for char in text if condition(char)]
    return Counter(filtered_chars)

text = "Hello123World456!"

# 数字のみカウント
digit_count = conditional_count(text, str.isdigit)
print(digit_count)  # Counter({'1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1})

# アルファベットのみカウント
alpha_count = conditional_count(text, str.isalpha)
print(alpha_count)  # Counter({'l': 3, 'o': 2, 'H': 1, 'e': 1, 'W': 1, 'r': 1, 'd': 1})

パフォーマンス比較

import time
from collections import Counter

def benchmark_counting_methods():
    text = "apple banana cherry " * 10000
    
    # count()メソッド
    start = time.time()
    apple_count = text.count("apple")
    time1 = time.time() - start
    
    # Counter
    start = time.time()
    words = text.split()
    word_counter = Counter(words)
    apple_count2 = word_counter["apple"]
    time2 = time.time() - start
    
    # 手動カウント
    start = time.time()
    words = text.split()
    apple_count3 = words.count("apple")
    time3 = time.time() - start
    
    print(f"text.count(): {time1:.6f}秒")
    print(f"Counter: {time2:.6f}秒")
    print(f"list.count(): {time3:.6f}秒")

benchmark_counting_methods()

統計情報の可視化準備

from collections import Counter

def get_frequency_stats(counter):
    """カウント結果から基本統計を計算"""
    if not counter:
        return {}
    
    values = list(counter.values())
    total = sum(values)
    
    stats = {
        'total_count': total,
        'unique_items': len(counter),
        'max_frequency': max(values),
        'min_frequency': min(values),
        'average_frequency': total / len(counter),
        'most_common': counter.most_common(1)[0] if counter else None
    }
    
    return stats

text = "Python is great and Python is powerful and Python is easy"
words = text.lower().split()
word_counter = Counter(words)

stats = get_frequency_stats(word_counter)
for key, value in stats.items():
    print(f"{key}: {value}")

まとめ

文字・文字列のカウント処理では、用途に応じて適切な方法を選択することが重要です:

  • 単純なカウント:count()メソッド
  • 複数要素の頻度解析:Counterクラス
  • 条件付きカウント:リスト内包表記との組み合わせ
  • 大規模データ:効率性を考慮した実装

これらを適切に使い分けることで、効果的なテキスト分析が可能になります。

らくらくPython塾 – 読むだけでマスター

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座

フリーランスボード

20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード

ITプロパートナーズ

週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ

Midworks 10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks