Гистограммы - еще один вид диаграмм, который помогает понять частоту или вероятность попадания точек данных в определенные интервалы или ячейки. Гистограммы особенно полезны, когда необходимо изучить центральную тенденцию, изменчивость и форму набора данных.
Для построения гистограммы также необходимы две оси - X и Y. Ось X (ячейки) представляет интервалы, на которые разделены данные. Диапазон данных сегментируется на "ячейки" или "корзины" (bin), которые охватывают равные диапазоны значений. А ось Y (частота) показывает количество точек данных в каждой ячейке.
Визуально гистограмма состоит из столбцов, где каждый столбец представляет собой табличную частоту или частоту появления точек данных для каждой ячейки, при этом высота отражает частоту. "Высота" столбца соответствует частоте или количеству точек данных, которые он представляет.
Форма гистограммы может предоставить много информации о статистическом распределении данных. Она может быть симметричной, асимметричной влево или вправо, одномодальной, бимодальной и т.д. Пик гистограммы может указывать на среднее или медианное значение данных.
Диапазон интервалов, которые охватывает гистограмма, указывает на изменчивость или разброс данных. Редкие столбцы или паттерн распределения с длинным хвостом в одном из хвостов гистограммы могут указывать на выбросы или пробелы в данных. При построении нескольких гистограмм друг над другом или рядом можно сравнивать различные наборы данных или свойства распределения, такие как центральная тенденция, разброс и форма.
Для построения гистограммы Matplotlib предоставляет функцию matplotlib.pyplot.hist()
matplotlib.pyplot.hist(x, bins=None, *, range=None, density=False, weights=None, cumulative=False, bottom=None,
histtype="bar", align="mid", orientation="vertical", rwidth=None,
log=False, color=None, label=None, stacked=False, data=None, **kwargs)
В реальности эта функция использует другую функцию - numpy.histogram. Эта функция группирует данных по оси Х по корзинам (bin) и подсчитывает количество значений в каждой корзине,
после чего отображает распределение.
Ключевые параметры функции:
x: входные значения в виде одного массива, либо последовательности массивов, длина которых не обязательно должна быть одинаковой.
bins: целое число, последовательность или строка, определяет количество равных по ширине ячеек в диапазоне.
Если bins - последовательность, она определяет границы ячеек, включая левую границу первой ячейки и правую границу последней ячейки; в этом случае ячейки могут быть
расположены неравномерно. Все ячейки, кроме последней (самой правой), являются полуоткрытыми. Другими словами, если bins=[1, 2, 3, 4],
то первый массив равен [1, 2) (включая 1, но исключая 2), а второй - [2, 3). Последний интервал - [3, 4], который включает число 4.
range: нижний и верхний пределы интервалов. Нижние и верхние выбросы игнорируются. Если не указано, range = (x.min(), x.max())
weights: массив весов той же формы, что и x. Каждое значение в x вносит только свой соответствующий вес в количество событий в интервале (вместо 1)
Одна из основных проблем при построении гистограмм заключается в выборе правильной ширины интервала. И здесь нет единого универсального правила, но есть несколько применяемых принципов:
Правило квадратного корня: для вычисления ширины применяется квадратный корень из количества точек данных в качестве количества интервалов.
Формула Стерджеса (Sturges formula): разбиение на интервалы (корзины) предполагает использование количества интервалов, равное log2(n)+1, где n - количество точек данных.
Правило Фридмана-Диакониса (Freedman-Diaconis rule): выбирает размер интервала на основе межквартильного размаха (IQR) и количества точек данных, чтобы минимизировать разницу между интервалом и фактическим распределением данных.
Рассмотрим простенькую гистограмму на примере случайных данных :
import matplotlib.pyplot as plt
import numpy as np
# генерируем случайные данные с нормальным распределением
data = np.random.randn(1000)
# вычисляем оптимальное количество контейнеров на основе правила Фридмана-Диакониса (Freedman-Diaconis rule)
q25, q75 = np.percentile(data, [25, 75])
bin_width = 2 * (q75 - q25) * len(data) ** (-1/3)
bins = int((data.max() - data.min()) / bin_width)
# Создаем гистограмму с оптимальным расположением интервалов в синем цвете
n, bins, patches = plt.hist(data, bins=bins, color="skyblue", edgecolor="black", alpha=0.7)
# Добавляем сетку для более удобного чтения гистограммы
plt.grid(True, which="both", linestyle="--", linewidth=0.5)
# Добавляем заголовки и подписи к осям
plt.title("Гистограмма", fontsize=15)
plt.xlabel("Значение", fontsize=12)
plt.ylabel("Частота", fontsize=12)
# Автоматически правим отступы
plt.tight_layout()
plt.show()
Здесь для генерации случайных чисел и различных математических вычислений применяется библиотека numpy, которая автоматически устанавливается вместе с matplotlib.
Так, вначале с помощью функции np.random.randn() создается массив data, который содержит 1000 случайных чисел:
data = np.random.randn(1000)
Вместо того чтобы выбирать количество столбиков (корзин/bin) на глаз, используеv статистический подход. В частности, вычисляем квартили: 25-й (q25) и 75-й (q75) перцентили, чтобы найти межквартильный размах:
q25, q75 = np.percentile(data, [25, 75])
Затем рассчитываем оптимальную ширину одного столбика:
bin_width = 2 * (q75 - q25) * len(data) ** (-1/3)
Рассчет производится по формуле bin_width = 2 * IQR / n√3, где IQR - межквартильный размах, а n - количество элементов.
Далее вычисляем количество интервалов:
bins = int((data.max() - data.min()) / bin_width)
Общий диапазон данных (от min до max) делится на полученную ширину, чтобы определить итоговое число столбиков (bins).
И далее функция plt.hist строит график, устанавливая в качестве цвета столбика небесно-голубой (skyblue) с черными границами столбцов и
небольшой прозрачностью (alpha=0.7 делает цвета чуть мягче). А вызов plt.grid() добавляет пунктирную сетку для удобства определения значений на осях.
n, bins, patches = plt.hist(data, bins=bins, color="skyblue", edgecolor="black", alpha=0.7) plt.grid(True, which="both", linestyle="--", linewidth=0.5)
В итоге получится следующая гистограмма:
Рассмотрим более простенькую гистограмму на реальных данных:
import matplotlib.pyplot as plt
days = ["20.01", "21.01", "22.01", "23.01", "24.01", "27.01", "28.01", "29.01", "30.01", "31.01", "03.02", "04.02", "05.02", "06.02", "07.02"]
usd = [77.76, 77.82, 77.52, 76.03, 75.92, 76.01, 76.55, 76.27, 76.02, 75.73, 77.02, 76.98, 76.91, 76.55, 77.05]
# Строим гистограмму
# bins=5 разбивает весь диапазон цен на 5 интервалов
plt.hist(usd, bins=5, color="skyblue", edgecolor="black", alpha=0.8)
plt.title("Распределение курса USD за период 20.01 - 07.02.2026", fontsize=14)
plt.xlabel("Курс доллара (руб.)", fontsize=12)
plt.ylabel("Количество дней", fontsize=12)
plt.grid(axis="y", linestyle="--", alpha=0.7)
plt.show()
Здесь в качестве данных мы имеем список days (даты) и список usd (курсы валют на эти даты). На основе этих данных можно построить гистограмму, однако важно понимать, что она будет показывать не изменение курса во времени, а частоту появления определенных диапазонов цен (например, сколько дней курс находился в интервале 76.0–76.5).
В данном случае у нас в списках 15 значений, и было бы оптимально поставить количество интервалов (bins) от 5 до 7, что и было сделано. Если поставить слишком много, каждый столбик будет высотой в 1 день, и график потеряет смысл.