Подсчет повторений в Python: от простого словаря до Counter

Раздел: Основы Python -> Подсчет и агрегация данных

Подсчет повторений в Python: обзор методов

В задачах обработки данных часто требуется определить, сколько раз каждый элемент встречается в коллекции - списке, строке, кортеже или массиве. Python предлагает несколько способов решения, от простого ручного подсчёта до специализированных структур данных. Выбор зависит от размера данных, требуемой производительности и удобства дальнейшей работы.

Наиболее эффективное решение: collections.Counter

Класс Counter из модуля collections создан специально для подсчёта повторений. Он принимает любую итерируемую последовательность и возвращает словарь, где ключ - элемент, а значение - количество его вхождений.


from collections import Counter

fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
counts = Counter(fruits)
print(counts)  # Counter({'apple': 3, 'banana': 2, 'orange': 1})

Python количество после запятой (количество знаков после запятой в python)

После создания объекта Counter можно обращаться к частоте конкретного элемента как к ключу словаря, использовать метод most_common(n) для получения N самых частых элементов, а также обновлять счётчик методом update().


print(counts['apple'])                # 3
print(counts.most_common(2))          # [('apple', 3), ('banana', 2)]
counts.update(['banana', 'orange'])
print(counts['banana'])               # 3

Python количество списков в списке (подсчет количества вложенных списков в python)

Counter автоматически обрабатывает отсутствие ключа (возвращает 0), что избавляет от проверок. Кроме того, он предоставляет операции над мультимножествами: сложение, вычитание, пересечение.

Возможные проблемы:

  • Элементы должны быть хешируемыми (неизменяемыми). Списки, словари или множества в качестве элементов вызовут ошибку TypeError: unhashable type. Решение - преобразовать их в кортежи или использовать идентификаторы.
  • Порядок элементов в Python 3.6 и ниже не гарантируется. В современных версиях Counter сохраняет порядок вставки, но не порядок частоты (для сортировки по частоте используйте most_common).
  • При работе с очень большими данными Counter потребляет память пропорционально количеству уникальных элементов. Если уникальных элементов много, это может быть затратно.

Ручной подсчёт с помощью обычного словаря

Как посчитать повторения без использования дополнительных модулей?

Классический подход - пройти по последовательности в цикле и увеличивать счётчик в словаре. Чтобы избежать KeyError при первом обращении к новому ключу, используют условие или метод dict.get().


fruits = ['apple', 'banana', 'apple', 'orange']
counts = {}
for fruit in fruits:
    counts[fruit] = counts.get(fruit, 0) + 1
print(counts)  # {'apple': 2, 'banana': 1, 'orange': 1}

Python количество повторений (подсчет количества повторений в python)

Типичные ошибки:

  • Забыть проверку существования ключа - приводит к KeyError.
  • Попытка изменить словарь во время итерации по его ключам - лучше создать новый словарь или использовать defaultdict.

Упрощение через collections.defaultdict

Как сделать ручной подсчёт более элегантным?

Класс defaultdict позволяет указать фабрику по умолчанию (например, int), которая автоматически создаёт значение 0 для отсутствующего ключа.


from collections import defaultdict

counts = defaultdict(int)
for fruit in fruits:
    counts[fruit] += 1
print(dict(counts))  # {'apple': 2, 'banana': 1, 'orange': 1}

количество символов python (подсчет количества символов в строке python)

Этот подход чуть компактнее и быстрее за счёт отсутствия вызова get() на каждой итерации.

Возможная проблема:

При сериализации (например, в JSON) defaultdict ведёт себя как обычный словарь, но нужно быть внимательным, если он используется как вложенная структура.

Использование list.count() для каждого уникального элемента

Как подсчитать повторения в списке самым простым способом?

Встроенный метод list.count(x) возвращает количество вхождений элемента x. Если вызвать его для каждого уникального элемента, получаем нужный подсчёт.


fruits = ['apple', 'banana', 'apple', 'orange']
unique = set(fruits)
counts = {fruit: fruits.count(fruit) for fruit in unique}
print(counts)

Python количество строк (подсчет количества строк в python)

Серьёзный недостаток:

Каждый вызов count() проходит по всему списку, поэтому общая сложность - O(n * m), где m - количество уникальных элементов. Для больших списков этот метод крайне неэффективен.

Подсчёт с помощью pandas.Series.value_counts()

Как подсчитать повторения в данных, если уже используется pandas?

Метод value_counts() возвращает серию с частотами значений, отсортированную по убыванию. Он удобен для фреймов данных и серий.


import pandas as pd

data = pd.Series(['apple', 'banana', 'apple', 'orange', 'banana'])
counts = data.value_counts()
print(counts)

количество цифр python (подсчет количества цифр в python)

apple     2
banana    2
orange    1
dtype: int64

Когда стоит избегать:

  • Если в проекте не используется pandas, установка библиотеки ради одного подсчёта избыточна.
  • Для маленьких списков накладные расходы на создание серии превышают выгоду.

Подсчёт в массивах numpy с помощью numpy.unique

Как посчитать повторения в числовых массивах?

Функция numpy.unique с параметром return_counts=True возвращает уникальные значения и их частоты.


import numpy as np

arr = np.array([1, 2, 1, 3, 2, 1])
values, counts = np.unique(arr, return_counts=True)
result = dict(zip(values, counts))
print(result)  # {1: 3, 2: 2, 3: 1}

Ограничение:

Работает только с массивами одного типа (обычно числовыми или строковыми). Для смешанных типов или вложенных структур не подходит.

Расширенные примеры подсчёта повторений

Подсчёт слов в тексте с учётом регистра и пунктуации

Пример

from collections import Counter
import re

text = "Python is great. Python is versatile! Is it? Yes, Python."
# Удаляем пунктуацию и приводим к нижнему регистру
words = re.findall(r'\b\w+\b', text.lower())
word_counts = Counter(words)
print(word_counts.most_common(3))
[('python', 3), ('is', 2), ('great', 1)]

Здесь используется регулярное выражение для выделения слов, а затем Counter для подсчёта.

Подсчёт повторений с учётом вложенных структур (списки списков)

Пример

from collections import Counter

data = [[1,2], [1,2], [3,4]]
# Преобразуем вложенные списки в кортежи для хеширования
counter = Counter(tuple(sublist) for sublist in data)
print(counter)
Counter({(1, 2): 2, (3, 4): 1})

Без преобразования в кортеж возникла бы ошибка TypeError: unhashable type: 'list'.

Получение топ-3 самых частых символов в строке

Пример

from collections import Counter

sentence = "abracadabra"
char_counts = Counter(sentence)
top_3 = char_counts.most_common(3)
print(top_3)
[('a', 5), ('b', 2), ('r', 2)]

Подсчёт повторений с использованием генератора для экономии памяти

Пример

from collections import Counter

def read_large_file(file_path):
    with open(file_path) as f:
        for word in f.read().split():
            yield word

# Используем генератор вместо загрузки всего файла в память
counter = Counter(read_large_file("large_text.txt"))
print(sum(counter.values()))  # общее количество слов

Генератор передаёт слова по одному, что позволяет обрабатывать большие файлы без переполнения памяти.

Подсчёт с условием (только элементы, встречающиеся более 2 раз)

Пример

from collections import Counter

items = [1,1,1,2,2,3,3,3,3]
counter = Counter(items)
filtered = {k: v for k, v in counter.items() if v > 2}
print(filtered)  # {1: 3, 3: 4}

Комбинация Counter с map и lambda для массовой обработки

Пример

from collections import Counter

names = ["alice", "bob", "alice", "bob", "bob"]
# Подсчёт без цикла (но неэффективно из-за многократного вызова Counter)
result = Counter(map(lambda x: x, names))
print(result)

Здесь map не даёт преимущества, но иллюстрирует возможность функционального подхода.

Подсчёт в DataFrame с группировкой по нескольким столбцам

Пример

import pandas as pd

df = pd.DataFrame({
    'city': ['Moscow', 'Moscow', 'SPb', 'SPb', 'Moscow'],
    'year': [2020, 2021, 2020, 2020, 2021]
})
# Подсчёт комбинаций city-year
combo_counts = df.groupby(['city', 'year']).size().reset_index(name='count')
print(combo_counts)
    city  year  count
0  Moscow  2020      1
1  Moscow  2021      2
2    SPb  2020      2

Подсчёт с использованием операций мультимножеств Counter

Пример

from collections import Counter

c1 = Counter(a=3, b=2, c=1)
c2 = Counter(a=1, b=2, d=3)
# Сложение - объединение мультимножеств
print(c1 + c2)  # Counter({'a': 4, 'b': 4, 'c': 1, 'd': 3})
# Вычитание - только положительные остатки
print(c1 - c2)  # Counter({'a': 2, 'c': 1})
# Пересечение - минимум
print(c1 & c2)  # Counter({'a': 1, 'b': 2})
# Объединение - максимум
print(c1 | c2)  # Counter({'a': 3, 'b': 2, 'c': 1, 'd': 3})

Подсчет количества повторений в Python - comments

En
Python количество повторений (python)