Нашли ошибку?
среднийNumPy 2.5.3

Гистограммы и подсчёт

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

Нужно знать:Статистикаsearchsorted и partition

Содержание статьи

Коротко

  • np.histogram(a, bins) возвращает пару: счётчики и границы интервалов (границ на одну больше).
  • bins — число интервалов одинаковой ширины или список границ.
  • Интервалы полуоткрытые [a, b), кроме последнего — он включает правую границу.
  • np.bincount(a) считает вхождения целых 0, 1, 2… — быстрее unique для небольших неотрицательных целых. С weights — суммы по группам.
  • np.digitize(a, bins) — номер интервала для каждого значения.

Синтаксис

counts, edges = np.histogram(a, bins=10, range=None, density=False)
np.bincount(x, weights=None, minlength=0)   # x — неотрицательные целые
np.digitize(a, bins, right=False)

Параметры

ПараметрЧто делаетПо умолчанию
binsчисло интервалов, список границ или правило вроде "auto"10
range(min, max) — диапазон для равных интервалов; значения вне него не считаютсяNone
densityTrue — плотность вместо счётчиков: площадь гистограммы равна 1False
weightsв bincount: вместо +1 прибавлять вес элементаNone
minlengthминимальная длина результата bincount0
rightв digitize: включать правую границу интервала вместо левойFalse

Примеры

Данные для примеровиспользуются во всех примерах ниже
ages = np.array([23, 35, 41, 29, 52, 38, 61, 27, 45, 33, 30, 58])
Гистограмма на 4 интервала
counts, edges = np.histogram(ages, bins=4)   # 4 интервала одинаковой ширины
print(counts)
edges
Вывод
[4 4 1 3]
array([23. , 32.5, 42. , 51.5, 61. ])
Свои границы
counts, edges = np.histogram(ages, bins=[20, 30, 40, 50, 70])   # свои границы
counts
Вывод
array([3, 4, 2, 3])
Доли вместо счётчиков
counts, edges = np.histogram(ages, bins=[20, 40, 70], density=True)
counts * np.diff(edges)                                    # доли; в сумме 1
Вывод
array([0.58333333, 0.41666667])
Подсчёт целых значений
rolls = np.array([3, 1, 3, 6, 2, 3, 6])
print(np.bincount(rolls))                  # сколько раз каждое число 0, 1, 2, …
np.bincount(rolls, minlength=8)
Вывод
[0 1 1 3 0 0 2]
array([0, 1, 1, 3, 0, 0, 2, 0])
Суммы по группам
store = np.array([0, 1, 0, 2, 1])          # номер магазина каждой продажи
amount = np.array([100, 250, 80, 40, 60])
np.bincount(store, weights=amount)         # сумма продаж по магазинам
Вывод
array([180., 310.,  40.])
Номер группы для каждого значения
np.digitize(ages, bins=[30, 45, 60])       # номер группы: 0 — до 30, 1 — 30–44, …
Вывод
array([0, 1, 1, 0, 2, 1, 3, 0, 2, 1, 1, 2])

Подводные камни

Последний интервал закрыт с двух сторон

Все интервалы [a, b), но последний — [a, b]. Поэтому максимум попадает в гистограмму, а не теряется.

Значение на правой границе
np.histogram(np.array([10, 20, 30]), bins=[10, 20, 30])   # 30 попало в последний интервал
Вывод
(array([1, 2]), array([10, 20, 30]))

bincount только для целых

Массив float не принимается, даже если значения целые по смыслу: NumPy не приводит дробный тип к целому сам. Приведите через astype(int).

bincount для floatошибка: TypeError
np.bincount(np.array([1.0, 2.0]))
Ошибка
TypeError: Cannot cast array data from dtype('float64') to dtype('int64') according to the rule 'safe'