Pandas.Series.value counts: примеры (PYTHON)

Подсчет уникальных значений с помощью value_counts в pandas
Раздел: Pandas, Статистика
pandas.Series.value_counts(normalize: bool=False, sort: bool=True, ascending: bool=False, bins: int=None, dropna: bool=True): pandas.Series

Функция pandas.Series.value_counts

Метод value_counts() принадлежит объекту pandas.Series и применяется для подсчета количества уникальных значений. Получение частотной статистики является одной из типовых операций при первичном анализе и очистке данных.

Функция находит применение при изучении распределения категориальных переменных, проверке на наличие аномалий или доминирующих значений, а также при оценке качества данных, например, подсчете пропусков, представленных отдельным значением.

Аргументы метода

  • normalize (bool, по умолчанию False): если установлено значение True, функция возвращает относительные частоты (доли) вместо абсолютных количеств.
  • sort (bool, по умолчанию True): определяет, следует ли сортировать результат по убыванию частоты.
  • ascending (bool, по умолчанию False): если параметр sort равен True, этот флаг задает порядок сортировки (по возрастанию).
  • bins (int, опционально): используется для числовых данных. Уникальные значения группируются в полуоткрытые интервалы заданного количества. Вместо самих значений в индекс результата помещаются объекты pandas.Interval.
  • dropna (bool, по умолчанию True): указывает, включать ли в подсчет значения NaN. При значении True записи с NaN исключаются из результата.

Возвращаемое значение

Метод возвращает новый объект pandas.Series, где индексами являются уникальные элементы исходной серии (или интервалы, если используется параметр bins), а значениями — их частоты или доли. По умолчанию ряд отсортирован по убыванию частоты.

Примеры использования value_counts

Базовый подсчет значений

import pandas as pd
s = pd.Series(['яблоко', 'банан', 'яблоко', 'апельсин', 'банан', 'яблоко'])
print(s.value_counts())
яблоко      3
банан       2
апельсин    1
dtype: int64

Получение относительных частот

print(s.value_counts(normalize=True))
яблоко      0.500000
банан       0.333333
апельсин    0.166667
dtype: float64

Сортировка по индексу

print(s.value_counts(sort=True, ascending=True))
апельсин    1
банан       2
яблоко      3
dtype: int64

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

s_num = pd.Series([1, 2, 5, 10, 12, 15, 20])
print(s_num.value_counts(bins=3))
(0.992, 7.333]    3
(13.667, 20.0]   2
(7.333, 13.667]  2
dtype: int64

Включение значений NaN в подсчет

s_with_na = pd.Series(['A', 'B', None, 'A', None, 'C'])
print(s_with_na.value_counts(dropna=False))
A        2
None     2
B        1
C        1
dtype: int64

Похожие функции в Python

Для подсчета уникальных элементов в последовательностях существуют альтернативные инструменты.

collections.Counter

Класс Counter из стандартной библиотеки предназначен для подсчета хешируемых объектов. Он возвращает словарь и удобен для работы с обычными списками или строками, но не с pandas-структурами.

from collections import Counter
lst = ['яблоко', 'банан', 'яблоко']
print(Counter(lst))
Counter({'яблоко': 2, 'банан': 1})

Метод Series.groupby().size()

Комбинация методов groupby() и size() дает аналогичный результат, но является более громоздкой. Ее применение оправдано в сложных сценариях агрегации, где помимо подсчета требуются другие операции.

s = pd.Series(['яблоко', 'банан', 'яблоко'])
print(s.groupby(s).size())
яблоко    2
банан     1
dtype: int64

Для большинства задач простого подсчета уникальных значений в Series метод value_counts() является оптимальным выбором благодаря своей простоте и наличию дополнительных параметров (normalize, bins, dropna). Counter чаще применяется за пределами экосистемы pandas.

Аналоги функции в других языках

PHP: array_count_values()

Функция подсчитывает количество всех значений массива, но работает только со строками и целыми числами.

$array = ['яблоко', 'банан', 'яблоко'];
print_r(array_count_values($array));
Array
(
    [яблоко] => 2
    [банан] => 1
)

JavaScript

Стандартной функции нет, обычно используют метод reduce.

const arr = ['яблоко', 'банан', 'яблоко'];
const counts = arr.reduce((acc, val) => {
  acc[val] = (acc[val] || 0) + 1;
  return acc;
}, {});
console.log(counts);
{ яблоко: 2, банан: 1 }

SQL (GROUP BY + COUNT)

Для получения частотной статистики применяется агрегирующий запрос.

SELECT fruit, COUNT(*) as count
FROM fruits_table
GROUP BY fruit
ORDER BY count DESC;

Java (Stream API)

Используют коллектор Collectors.groupingBy и Collectors.counting.

List list = Arrays.asList('яблоко', 'банан', 'яблоко');
Map counts = list.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counts);
{банан=1, яблоко=2}

Отличия от value_counts() заключаются в отсутствии в большинстве аналогов параметров для нормализации, работы с интервалами (bins) и управления NaN.

Распространенные ошибки

Применение к пустой серии

Метод возвращает пустую серию, что может нарушить ожидания последующего кода.

s = pd.Series([], dtype='object')
print(s.value_counts())
Series([], dtype: int64)

Некорректное использование bins с нечисловыми данными

Параметр bins предназначен только для числовых типов данных.

s = pd.Series(['a', 'b', 'c'])
try:
    s.value_counts(bins=2)
except Exception as e:
    print(f'Ошибка: {type(e).__name__}: {e}')
Ошибка: ValueError: Cannot use 'bins' with non-numeric data.

Большое количество уникальных значений

При наличии чрезвычайно высокой кардинальности данных (например, хешей) результат может занять много памяти. В таких случаях иногда целесообразнее проверить только количество уникальных значений через nunique().

Изменения в последних версиях pandas

В версии pandas 1.1.0 был добавлен параметр dropna, позволяющий контролировать подсчет значений NaN. По умолчанию он равен True, что сохраняет обратную совместимость — NaN исключаются из результата.

В более ранних версиях поведение при наличии NaN в данных было фиксированным — они просто не учитывались. Теперь, установив dropna=False, можно включить NaN в подсчет как отдельную категорию.

Расширенные примеры применения

Анализ распределения с визуализацией

Результат value_counts часто используется для построения графиков.

Пример python
import matplotlib.pyplot as plt
s = pd.Series(['A', 'B', 'A', 'C', 'B', 'B', 'A'])
counts = s.value_counts()
counts.plot(kind='bar')
plt.title('Частота значений')
plt.show()

Фильтрация редких или частых категорий

Можно отфильтровать исходные данные, оставив только значения, встречающиеся чаще определенного порога.

Пример python
s = pd.Series(['cat', 'dog', 'cat', 'bird', 'dog', 'elephant'])
frequent_values = s.value_counts()[s.value_counts() > 1].index
s_filtered = s[s.isin(frequent_values)]
print(s_filtered.unique())
['cat' 'dog']

Работа с пропущенными значениями как с отдельной категорией

Пример python
s = pd.Series([1.0, None, 2.0, None, 1.0, 3.0])
# Включаем NaN в подсчет и сортируем по индексу
counts_with_na = s.value_counts(dropna=False, sort=False).sort_index()
print(counts_with_na)
1.0    2
2.0    1
3.0    1
NaN    2
dtype: int64

Использование с cut для кастомных интервалов

Вместо параметра bins можно предварительно создать категории с помощью pd.cut.

Пример python
ages = pd.Series([12, 18, 25, 30, 35, 40, 45, 50])
age_bins = pd.cut(ages, bins=[0, 20, 40, 60])
print(age_bins.value_counts(sort=False))
(0, 20]     2
(20, 40]    4
(40, 60]    2
dtype: int64

Подсчет в подвыборках данных (в комбинации с groupby)

Пример python
df = pd.DataFrame({'Город': ['Москва', 'Москва', 'СПб', 'СПб', 'Москва'],
                   'Товар': ['Хлеб', 'Молоко', 'Хлеб', 'Хлеб', 'Молоко']})
# Подсчет частоты товаров в каждом городе
for city, group in df.groupby('Город'):
    print(f'Город: {city}')
    print(group['Товар'].value_counts())
    print()
Город: Москва
Молоко    2
Хлеб      1
dtype: int64

Город: СПб
Хлеб    2
dtype: int64

питон pandas.Series.value_counts function comments

En
Pandas.Series.value counts Return a Series containing counts of unique values