Histogram в Pandas: создание и анализ гистограмм для данных
Пройдите тест, узнайте какой профессии подходите
Для кого эта статья:
- аналитики данных и статистики
- обучающиеся на курсах аналитики данных
специалисты, заинтересованные в визуализации данных и использовании библиотеки Pandas
Когда массивы данных превращаются в неприступную стену цифр, гистограммы становятся вашим тайным оружием визуализации. Анализируя распределение значений одним взглядом, вы мгновенно выявляете закономерности, которые таблицы скрывают годами. 📊 Библиотека Pandas превратила создание этих мощных инструментов в дело нескольких строк кода, но правильная настройка и интерпретация результатов — вот где начинается настоящее искусство аналитики данных. Давайте разберемся, как превратить хаос числовых данных в наглядные гистограммы, раскрывающие истинную суть вашего датасета.
Устали от бесконечных таблиц и не можете решить, как эффективнее визуализировать данные? На Курсе «Аналитик данных» с нуля от Skypro вы научитесь создавать идеально настроенные гистограммы и другие виды визуализации в Pandas. Опытные эксперты покажут не только механизмы создания графиков, но и профессиональные приёмы их интерпретации, позволяющие принимать точные бизнес-решения. Переходите от текстовых таблиц к наглядным инсайтам уже через 6 месяцев обучения.
Что такое гистограммы и зачем они нужны в Pandas
Гистограмма — это графическое представление распределения числовых данных, где значения группируются в интервалы (бины), а высота столбцов отражает частоту или количество наблюдений в каждом интервале. По сути, это бар-чарт, который показывает плотность распределения данных.
В мире анализа данных гистограммы решают сразу несколько критических задач:
- Мгновенная оценка формы распределения (нормальное, скошенное, бимодальное)
- Выявление выбросов и аномалий в данных
- Определение центральной тенденции и разброса значений
- Проверка гипотез о распределении данных
- Сравнение распределений разных наборов данных
Библиотека Pandas делает создание гистограмм элементарным, интегрируя функциональность matplotlib с удобными методами DataFrame и Series. Это позволяет аналитикам быстро переходить от сырых данных к их визуальному исследованию.
Задача анализа | Что показывает гистограмма | Преимущество использования в Pandas |
---|---|---|
Распределение признака | Форму, модальность, асимметрию | Встроенные методы без сложной настройки |
Выявление выбросов | Изолированные столбцы вдали от основного распределения | Автоматическое масштабирование осей |
Проверка нормальности | Колоколообразную форму (или её отсутствие) | Возможность наложения теоретических распределений |
Сравнение групп | Различия в распределениях между подгруппами | Лёгкость создания множественных гистограмм |
Михаил Бернштейн, старший аналитик данных
Однажды мне поручили выяснить, почему новая модель прогнозирования спроса давала странные результаты для определенного региона. Таблицы с миллионами строк не давали никаких подсказок. Я создал гистограмму распределения заказов с помощью простого кода:
PythonСкопировать кодimport pandas as pd import matplotlib.pyplot as plt # Загрузка данных orders_df = pd.read_csv('regional_orders.csv') # Построение гистограммы orders_df['order_amount'].hist(bins=50) plt.title('Распределение объемов заказов') plt.xlabel('Объем заказа, руб.') plt.ylabel('Количество заказов') plt.show()
Гистограмма мгновенно выявила бимодальное распределение — два пика вместо ожидаемого одного. Оказалось, что в данных смешались заказы частных лиц и корпоративных клиентов с совершенно разными паттернами потребления. Разделив эти сегменты и построив отдельные модели, мы повысили точность прогнозов на 37%. Один график сэкономил недели работы.

Базовые методы создания гистограмм в Pandas
Pandas предлагает несколько элегантных способов создания гистограмм, адаптированных под различные сценарии анализа. Освоение этих базовых методов — первый шаг к мастерству визуализации данных. 📈
Самый простой способ создать гистограмму — использовать метод hist()
, который доступен как для объектов Series, так и для DataFrame:
# Для Series
df['column_name'].hist()
# Для всех числовых колонок DataFrame
df.hist()
Рассмотрим ключевые методы создания гистограмм в Pandas:
- Series.hist() — создает гистограмму для одного столбца данных
- DataFrame.hist() — генерирует сетку гистограмм для всех числовых столбцов
- DataFrame.plot.hist() — альтернативный интерфейс с дополнительными опциями
- pandas.plotting.hist_series() — низкоуровневая функция с расширенным контролем
Приведем пример комплексного использования этих методов:
import pandas as pd
import matplotlib.pyplot as plt
# Создаем тестовый DataFrame
df = pd.DataFrame({
'рост': np.random.normal(170, 10, 1000),
'вес': np.random.normal(70, 15, 1000),
'возраст': np.random.normal(35, 8, 1000)
})
# Метод 1: Гистограмма одного столбца
df['рост'].hist(bins=20, color='skyblue', edgecolor='black')
plt.title('Распределение роста')
plt.show()
# Метод 2: Гистограммы всех числовых столбцов
df.hist(figsize=(12, 4), bins=15, color='lightgreen',
grid=False, layout=(1, 3))
plt.tight_layout()
plt.show()
# Метод 3: Использование plot.hist()
df.plot.hist(alpha=0.7, bins=20, subplots=True,
layout=(3, 1), figsize=(10, 8))
plt.show()
Каждый из этих методов имеет свои нюансы и преимущества в зависимости от задачи:
Метод | Сценарий использования | Особенности |
---|---|---|
Series.hist() | Анализ одиночной переменной | Лаконичный код, быстрое исследование |
DataFrame.hist() | Сравнение нескольких переменных | Автоматическая компоновка нескольких графиков |
DataFrame.plot.hist() | Презентационные графики | Расширенные возможности стилизации |
pandas.plotting.hist_series() | Специализированные гистограммы | Наибольший контроль над графиком |
При работе с большими наборами данных важно учитывать производительность. Для датасетов объемом более миллиона записей рекомендуется использовать параметр bins='auto'
и метод plot.hist()
, который эффективнее обрабатывает большие массивы.
Настройка параметров гистограмм для точного анализа
Настройка параметров гистограммы определяет, насколько точно график отражает истинное распределение данных. Правильно настроенная гистограмма — это разница между обнаружением ключевого инсайта и пропуском важной закономерности. 🔍
Самым критичным параметром является количество интервалов (bins). Слишком мало — и вы потеряете детали распределения; слишком много — и график станет зашумленным:
# Сравнение различного количества bins
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
df['доход'].hist(bins=5, ax=axes[0], color='coral')
axes[0].set_title('5 интервалов (слишком мало)')
df['доход'].hist(bins=20, ax=axes[1], color='lightblue')
axes[1].set_title('20 интервалов (оптимально)')
df['доход'].hist(bins=100, ax=axes[2], color='lightgreen')
axes[2].set_title('100 интервалов (слишком много)')
plt.tight_layout()
Рассмотрим ключевые параметры для настройки гистограмм в Pandas:
- bins — количество интервалов или их границы в виде списка
- range — ограничение диапазона данных (мин, макс)
- density — нормализация гистограммы для получения плотности вероятности
- cumulative — построение кумулятивной гистограммы
- alpha — прозрачность столбцов (полезно при наложении гистограмм)
- grid — отображение сетки для улучшения восприятия
- figsize — размер графика в дюймах
Рассмотрим пример тонкой настройки гистограммы для анализа асимметричных данных:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Создаем асимметричные данные (например, доходы населения)
skewed_data = np.random.lognormal(mean=8, sigma=1, size=10000)
df = pd.DataFrame({'доход': skewed_data})
# Создаем оптимизированную гистограмму
plt.figure(figsize=(10, 6))
df['доход'].hist(
bins=40, # Оптимальное количество интервалов
color='skyblue', # Цвет столбцов
alpha=0.8, # Полупрозрачность
density=True, # Нормализация по площади
edgecolor='white', # Границы столбцов
range=(0, 30000) # Обрезаем экстремальные выбросы
)
# Добавляем линию плотности вероятности для сравнения
df['доход'].plot(kind='kde', color='darkblue', linewidth=2)
plt.title('Распределение доходов населения', fontsize=14)
plt.xlabel('Доход, тыс. руб.', fontsize=12)
plt.ylabel('Плотность', fontsize=12)
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()
Для определения оптимального числа интервалов существуют различные методы:
Правило | Формула | Случаи применения |
---|---|---|
Правило Стерджеса | 1 + log₂(n) | Для нормального распределения |
Правило Фридмана-Диакониса | 2 × IQR × n⁻⅓ | Устойчиво к выбросам |
Правило Скотта | 3.5 × σ × n⁻⅓ | Для приближенно нормального распределения |
Квадратный корень | √n | Простое эмпирическое правило |
В Pandas можно использовать эти правила, указав соответствующее строковое значение в параметре bins:
# Автоматический подбор количества интервалов
df['column'].hist(bins='auto') # Правило Фридмана-Диакониса
df['column'].hist(bins='sturges') # Правило Стерджеса
df['column'].hist(bins='scott') # Правило Скотта
df['column'].hist(bins='fd') # Синоним Фридмана-Диакониса
Интерпретация гистограмм: что показывают распределения
Анна Ковалева, руководитель аналитического отдела
В прошлом году мы запустили программу оптимизации времени доставки наших товаров. Мой коллега уверял всех, что среднее время доставки снизилось на 15% после внедрения новой логистической системы. Но клиенты продолжали жаловаться.
Я построила гистограммы времени доставки "до" и "после":
PythonСкопировать код# Построение наложенных гистограмм fig, ax = plt.subplots(figsize=(10, 6)) before_df['delivery_time'].hist(alpha=0.5, bins=30, label='До оптимизации', ax=ax) after_df['delivery_time'].hist(alpha=0.5, bins=30, label='После оптимизации', ax=ax) ax.set_xlabel('Время доставки (часы)') ax.set_ylabel('Количество заказов') ax.legend() plt.show()
Гистограмма раскрыла истину: среднее действительно снизилось, но из-за бимодального распределения. Новая система ускорила доставку в центральные районы (первый пик), но периферийные районы (второй пик) стали обслуживаться даже медленнее. Вдобавок появился "длинный хвост" экстремально долгих доставок.
Инсайт позволил нам перенастроить логистику для периферийных зон и добиться реального улучшения, подтвержденного гистограммой с нормальным распределением и без "хвостов".
Гистограмма — это намного больше, чем просто набор столбцов. Её форма рассказывает удивительно детальную историю о распределении ваших данных. 📝 Умение " читать" гистограммы превращает аналитика из простого технического специалиста в стратега, способного выявлять неочевидные закономерности.
Основные характеристики распределений, видимые на гистограммах:
- Центральная тенденция — где сосредоточена масса данных
- Разброс — насколько широко разбросаны значения
- Форма — симметричная, скошенная, многомодальная
- Выбросы — изолированные значения вне основного распределения
- Пробелы — отсутствующие значения в определенных диапазонах
Давайте рассмотрим основные типы распределений, которые вы можете встретить на практике:
Тип распределения | Как выглядит на гистограмме | Интерпретация и применение |
---|---|---|
Нормальное (Гауссово) | Колоколообразная симметричная форма | Естественные процессы, многие биологические параметры |
Правосторонняя асимметрия | Пик слева, "хвост" справа | Доходы, цены, время ожидания |
Левосторонняя асимметрия | Пик справа, "хвост" слева | Возраст смерти, результаты тестов с "потолком" |
Бимодальное | Два отчетливых пика | Смесь двух групп, например, возрасты учеников и учителей |
Равномерное | Примерно одинаковая высота всех столбцов | Случайные процессы, округленные данные |
Мультимодальное | Несколько пиков | Несколько подгрупп в данных |
Для эффективной интерпретации гистограмм в Pandas можно использовать дополнительные элементы:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# Создаем смесь двух нормальных распределений
group1 = np.random.normal(loc=5, scale=1, size=1000)
group2 = np.random.normal(loc=10, scale=1.5, size=1000)
mixed_data = np.concatenate([group1, group2])
df = pd.DataFrame({'значения': mixed_data})
# Создаем гистограмму с дополнительными элементами
plt.figure(figsize=(12, 6))
# Основная гистограмма
n, bins, patches = plt.hist(df['значения'], bins=40,
alpha=0.7, color='skyblue',
density=True, edgecolor='white')
# Добавляем линию плотности вероятности
x = np.linspace(df['значения'].min(), df['значения'].max(), 100)
kde = stats.gaussian_kde(df['значения'])
plt.plot(x, kde(x), 'r-', linewidth=2, label='KDE')
# Добавляем вертикальные линии для статистических показателей
plt.axvline(df['значения'].mean(), color='red', linestyle='dashed',
linewidth=2, label=f'Среднее: {df["значения"].mean():.2f}')
plt.axvline(df['значения'].median(), color='green', linestyle='dashed',
linewidth=2, label=f'Медиана: {df["значения"].median():.2f}')
plt.axvline(df['значения'].mode().iloc[0], color='purple', linestyle='dashed',
linewidth=2, label=f'Мода: {df["значения"].mode().iloc[0]:.2f}')
# Добавляем аннотации и оформление
plt.title('Интерпретация бимодального распределения', fontsize=14)
plt.xlabel('Значение', fontsize=12)
plt.ylabel('Плотность вероятности', fontsize=12)
plt.legend()
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
При интерпретации гистограмм важно учитывать контекст данных и избегать типичных ошибок:
- Не путать частоту с важностью — высокий столбец не всегда означает важный сегмент
- Учитывать влияние выбросов на среднее — при асимметричных распределениях медиана информативнее
- Помнить о "ложных бимодальностях" из-за неоптимального числа bins
- Сочетать анализ гистограмм с формальными статистическими тестами
- Быть осторожным с интерпретацией "хвостов" распределения, где число наблюдений мало
Определились с направлением в аналитике данных после изучения гистограмм? Тест на профориентацию от Skypro поможет выяснить, какая специализация в анализе данных подойдет именно вам. Выясните, стоит ли вам погружаться в статистический анализ, визуализацию данных или машинное обучение всего за 5 минут. Получите персональные рекомендации по развитию навыков работы с данными, основанные на вашем опыте, интересах и способностях.
Продвинутые техники работы с гистограмmmi в Pandas
Освоив базовые методы, пора перейти к продвинутым техникам, которые превратят ваши гистограммы из простых диаграмм в мощные инструменты анализа. 🚀 Эти методы позволяют глубже погрузиться в данные и извлечь максимум информации из распределений.
Рассмотрим несколько продвинутых техник:
- Наложение нескольких гистограмм для сравнения распределений
- Комбинирование с другими визуализациями (box plot, violin plot)
- Условные гистограммы для анализа подгрупп
- Логарифмические преобразования для работы с данными большого диапазона
- Интеграция статистических тестов с визуализацией
Давайте рассмотрим пример продвинутой техники — наложение нескольких гистограмм с полупрозрачностью для сравнения:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import PercentFormatter
# Создаем DataFrame с данными о скорости загрузки страниц в разных браузерах
np.random.seed(42)
data = {
'Chrome': np.random.gamma(shape=2, scale=0.5, size=1000),
'Firefox': np.random.gamma(shape=2.2, scale=0.6, size=1000),
'Safari': np.random.gamma(shape=1.8, scale=0.7, size=1000)
}
df = pd.DataFrame(data)
# Создаем гистограммы с наложением
plt.figure(figsize=(12, 7))
# Общие параметры для всех гистограмм
params = dict(
alpha=0.5, # Полупрозрачность для наложения
bins=30, # Одинаковое количество бинов
density=True, # Нормализация площади
histtype='stepfilled', # Тип гистограммы с заливкой
)
# Строим гистограммы для каждого браузера
browsers = ['Chrome', 'Firefox', 'Safari']
colors = ['#4285F4', '#FF9800', '#34A853']
for browser, color in zip(browsers, colors):
df[browser].hist(label=browser, color=color, **params)
# Оформляем график
plt.title('Сравнение времени загрузки страниц в разных браузерах', fontsize=15)
plt.xlabel('Время загрузки (секунды)', fontsize=12)
plt.ylabel('Плотность вероятности', fontsize=12)
plt.grid(alpha=0.3)
plt.legend(title='Браузер')
# Добавляем вертикальные линии средних значений
for browser, color in zip(browsers, colors):
plt.axvline(df[browser].mean(), color=color, linestyle='--',
linewidth=2, label=f'_Среднее {browser}')
plt.tight_layout()
plt.show()
Еще одна мощная техника — создание 2D-гистограмм для анализа взаимосвязей между двумя числовыми переменными:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Создаем данные для 2D-гистограммы
mean = [0, 0]
cov = [[1, 0.5], [0\.5, 1]]
x, y = np.random.multivariate_normal(mean, cov, 10000).T
df = pd.DataFrame({'x': x, 'y': y})
# Создаем 2D-гистограмму
plt.figure(figsize=(10, 8))
plt.hist2d(df['x'], df['y'], bins=50, cmap='viridis')
plt.colorbar(label='Частота')
plt.title('2D-гистограмма корреляции переменных', fontsize=14)
plt.xlabel('Переменная X', fontsize=12)
plt.ylabel('Переменная Y', fontsize=12)
plt.tight_layout()
plt.show()
Для более сложных сценариев анализа можно использовать сочетание гистограмм с другими типами визуализаций:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Создаем синтетические данные с группами
np.random.seed(42)
n = 1000
groups = ['Группа A', 'Группа B', 'Группа C']
data = {
'значение': np.concatenate([
np.random.normal(5, 1, n),
np.random.normal(6, 1.5, n),
np.random.normal(4, 2, n)
]),
'группа': np.repeat(groups, n)
}
df = pd.DataFrame(data)
# Создаем комбинированную визуализацию
plt.figure(figsize=(14, 10))
# 1. Общая гистограмма
plt.subplot(2, 2, 1)
sns.histplot(data=df, x='значение', kde=True)
plt.title('Общая гистограмма')
# 2. Гистограммы по группам
plt.subplot(2, 2, 2)
sns.histplot(data=df, x='значение', hue='группа',
element='step', common_norm=False)
plt.title('Гистограммы по группам')
# 3. Box plot для сравнения
plt.subplot(2, 2, 3)
sns.boxplot(data=df, x='группа', y='значение')
plt.title('Box Plot по группам')
# 4. Violin plot для распределений
plt.subplot(2, 2, 4)
sns.violinplot(data=df, x='группа', y='значение', inner='quartile')
plt.title('Violin Plot по группам')
plt.tight_layout()
plt.show()
Интерактивные гистограммы с использованием библиотеки Plotly позволяют исследовать данные более детально:
import pandas as pd
import numpy as np
import plotly.express as px
# Создаем данные
np.random.seed(42)
df = pd.DataFrame({
'категория': np.repeat(['A', 'B', 'C'], 1000),
'значение': np.concatenate([
np.random.normal(0, 1, 1000),
np.random.normal(3, 2, 1000),
np.random.normal(-2, 1.5, 1000)
])
})
# Создаем интерактивную гистограмму
fig = px.histogram(
df, x='значение', color='категория',
marginal='box', # Добавляем box plot на полях
opacity=0.7, # Прозрачность для наложения
barmode='overlay', # Режим наложения
histnorm='probability density', # Нормализация
hover_data=df.columns # Данные при наведении
)
# Настраиваем внешний вид
fig.update_layout(
title='Интерактивная гистограмма с группировкой',
xaxis_title='Значение переменной',
yaxis_title='Плотность',
legend_title='Категория'
)
fig.show()
Использование условных гистограмм в сочетании с другими статистиками позволяет проводить более глубокий анализ данных:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# Создаем DataFrame с данными о доходе по регионам
regions = ['Север', 'Юг', 'Запад', 'Восток']
data = {}
np.random.seed(42)
for region in regions:
if region == 'Север':
data[region] = np.random.lognormal(mean=10, sigma=0.4, size=1000)
elif region == 'Юг':
data[region] = np.random.lognormal(mean=9.8, sigma=0.5, size=1000)
elif region == 'Запад':
data[region] = np.random.lognormal(mean=10.2, sigma=0.3, size=1000)
else: # Восток
data[region] = np.random.lognormal(mean=10.1, sigma=0.6, size=1000)
# Подготавливаем данные для анализа
df_income = pd.DataFrame(data)
df_melted = df_income.melt(var_name='region', value_name='income')
# Создаем фигуру с несколькими подграфиками
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
axes = axes.flatten()
# Статистические данные для аннотаций
stats_data = {}
for i, region in enumerate(regions):
# Рассчитываем статистики
mean_val = df_income[region].mean()
median_val = df_income[region].median()
skew_val = stats.skew(df_income[region])
kurtosis_val = stats.kurtosis(df_income[region])
stats_data[region] = {
'mean': mean_val,
'median': median_val,
'skewness': skew_val,
'kurtosis': kurtosis_val
}
# Строим гистограмму
df_income[region].hist(bins=30, alpha=0.7, ax=axes[i],
density=True, color=f'C{i}')
# Добавляем KDE
x = np.linspace(df_income[region].min(), df_income[region].max(), 100)
axes[i].plot(x, stats.kde.gaussian_kde(df_income[region])(x),
'r-', linewidth=2)
# Добавляем вертикальные линии для среднего и медианы
axes[i].axvline(mean_val, color='red', linestyle='-',
label=f'Среднее: {mean_val:.0f}')
axes[i].axvline(median_val, color='green', linestyle='-',
label=f'Медиана: {median_val:.0f}')
# Добавляем статистические аннотации
stats_text = (f'Асимметрия: {skew_val:.2f}\n'
f'Эксцесс: {kurtosis_val:.2f}')
axes[i].text(0.95, 0.95, stats_text, transform=axes[i].transAxes,
verticalalignment='top', horizontalalignment='right',
bbox=dict(boxstyle='round', facecolor='white', alpha=0.7))
axes[i].set_title(f'Распределение дохода: {region}')
axes[i].set_xlabel('Доход')
axes[i].set_ylabel('Плотность')
axes[i].legend()
axes[i].grid(alpha=0.3)
plt.tight_layout()
plt.show()
Гистограммы в Pandas — это не просто способ показать распределение данных, а мощный инструмент принятия стратегических решений. Мы рассмотрели все аспекты их создания и интерпретации: от базового синтаксиса до продвинутых техник наложения и комбинирования с другими визуализациями. Правильное понимание формы распределения — ключ к выявлению скрытых закономерностей, определению аномалий и проверке статистических гипотез. Помните: эффективная визуализация превращает тысячи строк данных в ясное понимание происходящего, а это уже половина успеха в современной аналитике.