Python Counter и defaultdict: подсчёт и группировка данных

Категория: Python · Язык: Python · Обновлено:

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

Подсчёт элементов через Counter

Python
from collections import Counter

words = "кот пёс кот рыба кот пёс".split()
counts = Counter(words)

print(counts)                    # Counter({'кот': 3, 'пёс': 2, 'рыба': 1})
print(counts["кот"])             # 3
print(counts["слон"])            # 0
print(counts.most_common(2))     # [('кот', 3), ('пёс', 2)]
print(sum(counts.values()))      # 6

Для отсутствующего ключа Counter возвращает 0 и не бросает KeyError. Метод most_common(n) отдаёт n самых частых элементов.

Обновление и арифметика

Python
counts.update(["рыба", "рыба", "слон"])
print(counts["рыба"])            # 3
print(counts["слон"])            # 1

a = Counter("aab")
b = Counter("abc")
print(a + b)                     # Counter({'a': 3, 'b': 2, 'c': 1})
print(a - b)                     # Counter({'a': 1})
print(list(counts.elements())[:3])  # ['кот', 'кот', 'кот']

Группировка через defaultdict

Python
from collections import defaultdict

people = [("Анна", "Москва"), ("Игорь", "Казань"), ("Ольга", "Москва")]

by_city = defaultdict(list)
for name, city in people:
    by_city[city].append(name)

print(dict(by_city))             # {'Москва': ['Анна', 'Ольга'], 'Казань': ['Игорь']}
print(by_city["Сочи"])           # []

Аргумент list это фабрика значений: при обращении к новому ключу создаётся пустой список. Обратите внимание, что чтение несуществующего ключа тоже создаёт его.

Подсчёт и суммирование через defaultdict

Python
sales = [("хлеб", 3), ("сыр", 1), ("хлеб", 2)]

total = defaultdict(int)
for item, amount in sales:
    total[item] += amount

print(dict(total))               # {'хлеб': 5, 'сыр': 1}

Без collections: setdefault и get

Python
groups = {}
for name, city in people:
    groups.setdefault(city, []).append(name)

print(groups["Москва"])                 # ['Анна', 'Ольга']

counts_plain = {}
for word in words:
    counts_plain[word] = counts_plain.get(word, 0) + 1

print(counts_plain["кот"])              # 3

Что выбрать

Задача

Инструмент

Подсчитать, сколько раз встречается элемент

Counter

Найти самые частые значения

Counter.most_common

Сгруппировать значения по ключу

defaultdict(list)

Суммировать значения по ключу

defaultdict(int)

Группировка уже отсортированных данных

itertools.groupby

Частые вопросы

Как найти самый редкий элемент в Counter?

Возьмите последние пары: counts.most_common()[-1] или min(counts, key=counts.get).

Как превратить defaultdict в обычный словарь?

Передайте его в dict(...), как в примерах выше. Так отсутствующие ключи перестанут создаваться при чтении.

Чем Counter отличается от обычного словаря?

У Counter есть арифметика (+, -), метод most_common и значение 0 для отсутствующих ключей. В остальном это подкласс dict.