Histogram в Pandas: создание и анализ гистограмм для данных

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Для кого эта статья:

  • аналитики данных и статистики
  • обучающиеся на курсах аналитики данных
  • специалисты, заинтересованные в визуализации данных и использовании библиотеки 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%. Один график сэкономил недели работы.

Кинга Идем в IT: пошаговый план для смены профессии

Базовые методы создания гистограмм в Pandas

Pandas предлагает несколько элегантных способов создания гистограмм, адаптированных под различные сценарии анализа. Освоение этих базовых методов — первый шаг к мастерству визуализации данных. 📈

Самый простой способ создать гистограмму — использовать метод hist(), который доступен как для объектов Series, так и для DataFrame:

Python
Скопировать код
# Для Series
df['column_name'].hist()

# Для всех числовых колонок DataFrame
df.hist()

Рассмотрим ключевые методы создания гистограмм в Pandas:

  • Series.hist() — создает гистограмму для одного столбца данных
  • DataFrame.hist() — генерирует сетку гистограмм для всех числовых столбцов
  • DataFrame.plot.hist() — альтернативный интерфейс с дополнительными опциями
  • pandas.plotting.hist_series() — низкоуровневая функция с расширенным контролем

Приведем пример комплексного использования этих методов:

Python
Скопировать код
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). Слишком мало — и вы потеряете детали распределения; слишком много — и график станет зашумленным:

Python
Скопировать код
# Сравнение различного количества 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 — размер графика в дюймах

Рассмотрим пример тонкой настройки гистограммы для анализа асимметричных данных:

Python
Скопировать код
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:

Python
Скопировать код
# Автоматический подбор количества интервалов
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 можно использовать дополнительные элементы:

Python
Скопировать код
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

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

Рассмотрим несколько продвинутых техник:

  1. Наложение нескольких гистограмм для сравнения распределений
  2. Комбинирование с другими визуализациями (box plot, violin plot)
  3. Условные гистограммы для анализа подгрупп
  4. Логарифмические преобразования для работы с данными большого диапазона
  5. Интеграция статистических тестов с визуализацией

Давайте рассмотрим пример продвинутой техники — наложение нескольких гистограмм с полупрозрачностью для сравнения:

Python
Скопировать код
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-гистограмм для анализа взаимосвязей между двумя числовыми переменными:

Python
Скопировать код
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()

Для более сложных сценариев анализа можно использовать сочетание гистограмм с другими типами визуализаций:

Python
Скопировать код
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 позволяют исследовать данные более детально:

Python
Скопировать код
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()

Использование условных гистограмм в сочетании с другими статистиками позволяет проводить более глубокий анализ данных:

Python
Скопировать код
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 — это не просто способ показать распределение данных, а мощный инструмент принятия стратегических решений. Мы рассмотрели все аспекты их создания и интерпретации: от базового синтаксиса до продвинутых техник наложения и комбинирования с другими визуализациями. Правильное понимание формы распределения — ключ к выявлению скрытых закономерностей, определению аномалий и проверке статистических гипотез. Помните: эффективная визуализация превращает тысячи строк данных в ясное понимание происходящего, а это уже половина успеха в современной аналитике.