Violin Plot в Python: мощный инструмент визуализации данных

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

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

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

  • профессионалы в области аналитики данных
  • студенты и начинающие аналитики, изучающие визуализацию данных
  • специалисты, работающие с Python и библиотеками для анализа данных

Визуализация данных — ключевой компонент аналитики, позволяющий превращать числовые массивы в интуитивно понятные образы. Среди множества инструментов Python особое место занимает Violin Plot — элегантное решение для детального анализа распределения данных. Этот график объединяет преимущества box plot и kernel density plot, позволяя одновременно оценить медиану, квартили, плотность распределения и выбросы. В 2025 году, когда объемы анализируемых данных продолжают расти экспоненциально, Violin Plot становится незаменимым инструментом для тех, кто стремится извлечь максимум информации из своих датасетов. 📊🎻

Хотите освоить передовые методы визуализации данных, включая Violin Plot и другие мощные инструменты? Курс «Аналитик данных» с нуля от Skypro — это ваш путь к профессиональному владению Python для анализа данных. Курс включает практические проекты с реальными данными, где вы научитесь создавать информативные визуализации, которые помогают принимать обоснованные решения. Инвестируйте в свои навыки сейчас, чтобы стать востребованным специалистом на рынке аналитики!

Что такое Violin Plot и его роль в анализе данных

Violin Plot (скрипичная диаграмма) представляет собой гибридный инструмент визуализации, сочетающий в себе элементы box plot (ящик с усами) и kernel density plot (график плотности вероятности). Название происходит от характерной формы графика, напоминающей скрипку или виолончель. 🎻

Основная ценность Violin Plot заключается в его способности одновременно отображать:

  • Полное распределение данных (через кривые плотности вероятности)
  • Медиану и квартили (через внутренние элементы "ящика")
  • Минимумы и максимумы (через "усы")
  • Выбросы (через отдельные точки)
  • Сравнительную плотность вероятности на разных участках распределения (через ширину "скрипки")

Алексей Петров, старший аналитик данных

Я столкнулся с необходимостью проанализировать время отклика API в различных географических регионах. Традиционные графики показывали только среднее значение и стандартное отклонение, что скрывало критические аномалии в данных. Внедрив Violin Plot в наш аналитический дашборд, мы обнаружили бимодальное распределение в некоторых регионах — это указывало на периодические проблемы с сетевой инфраструктурой. Благодаря этой находке мы оптимизировали маршрутизацию трафика и снизили время отклика на 37%. Скрипичные диаграммы позволили увидеть то, что оставалось невидимым на стандартных графиках, и это кардинально изменило наш подход к мониторингу производительности.

Преимущества Violin Plot по сравнению с другими методами визуализации:

Тип графикаОтображение распределенияПоказ статистических метрикСравнение группВизуализация бимодальности
Violin PlotПолное + плотностьМедиана, квартили, диапазонОтличноеЯвное
Box PlotОграниченноеМедиана, квартили, диапазонХорошееОтсутствует
HistogramДискретноеТолько визуальноОграниченноеВидимое, но неточное
Density PlotНепрерывноеОтсутствуютСреднееВидимое

Violin Plot становится особенно ценным в следующих ситуациях:

  • При анализе асимметричных распределений, где среднее значение не является репрезентативным
  • При выявлении мультимодальных распределений (имеющих несколько "пиков")
  • При сравнении нескольких групп данных с различной структурой распределения
  • При необходимости детального анализа выбросов в контексте всего распределения
Кинга Идем в IT: пошаговый план для смены профессии

Создание базовых Violin Plot в Python с помощью Seaborn

Библиотека Seaborn делает создание Violin Plot в Python исключительно простым и гибким процессом. Рассмотрим основные способы построения скрипичных диаграмм с использованием различных наборов данных. 🐍

Для начала необходимо импортировать все необходимые библиотеки:

Python
Скопировать код
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Установка стиля Seaborn
sns.set(style="whitegrid")

Базовый Violin Plot можно создать буквально одной строкой кода:

Python
Скопировать код
# Загрузка демонстрационного набора данных
tips = sns.load_dataset("tips")

# Создание базового Violin Plot
plt.figure(figsize=(10, 6))
sns.violinplot(x="day", y="total_bill", data=tips)
plt.title("Распределение счетов по дням недели")
plt.show()

Для сравнения нескольких категорий с дополнительной группировкой:

Python
Скопировать код
# Violin Plot с группировкой по полу
plt.figure(figsize=(12, 7))
sns.violinplot(x="day", y="total_bill", hue="sex", data=tips, split=True, palette="Set2")
plt.title("Распределение счетов по дням недели и полу клиентов")
plt.show()

Ключевые параметры функции violinplot в Seaborn:

ПараметрОписаниеВозможные значения
dataDataFrame с даннымиpandas.DataFrame
x, yПеременные для осей X и YИмена столбцов в DataFrame
hueГруппировка по категориямИмя категориального столбца
splitРазделение "скрипок" для hueTrue/False
innerПредставление внутри "скрипки""box", "quartile", "point", "stick", None
scaleМетод масштабирования ширины"area", "count", "width"
bwСглаживание кривой плотностиfloat или {"scott", "silverman"}

Для работы с собственными данными вы можете использовать DataFrame из любого источника:

Python
Скопировать код
# Пример с загрузкой данных из CSV
# df = pd.read_csv("path_to_your_data.csv")
# sns.violinplot(x="category_column", y="numeric_column", data=df)

# Пример с созданием синтетических данных
np.random.seed(42)
categories = ['A', 'B', 'C', 'D']
data = pd.DataFrame({
'category': np.random.choice(categories, 1000),
'value': np.concatenate([
np.random.normal(0, 1, 250), # Нормальное распределение для A
np.random.gamma(2, 2, 250), # Гамма-распределение для B
np.random.exponential(2, 250), # Экспоненциальное для C
np.concatenate([np.random.normal(-3, 1, 125), np.random.normal(3, 1, 125)]) # Бимодальное для D
])
})

plt.figure(figsize=(12, 7))
sns.violinplot(x="category", y="value", data=data, inner="quartile", palette="viridis")
plt.title("Violin Plot различных распределений")
plt.show()

Для сравнения с другими типами визуализаций можно совместить несколько графиков:

Python
Скопировать код
# Сравнение Violin Plot с Box Plot
plt.figure(figsize=(15, 6))

plt.subplot(1, 2, 1)
sns.violinplot(x="category", y="value", data=data, inner="quartile")
plt.title("Violin Plot")

plt.subplot(1, 2, 2)
sns.boxplot(x="category", y="value", data=data)
plt.title("Box Plot")

plt.tight_layout()
plt.show()

Настройка и стилизация Violin Plot для презентаций

Профессиональная визуализация данных требует не только информативности, но и эстетического оформления, особенно для презентаций и публикаций. Seaborn предоставляет обширные возможности для настройки внешнего вида Violin Plot. 🎨

Начнем с базовой настройки стилей Seaborn:

Python
Скопировать код
# Установка стилей для презентационного качества
sns.set(style="whitegrid", context="talk", palette="pastel")
plt.figure(figsize=(12, 8))

# Создание основного графика с улучшенным стилем
vp = sns.violinplot(x="day", y="total_bill", data=tips, inner="quartile", 
palette="Set2", linewidth=1.5, saturation=0.8)

# Настройка осей и заголовков
plt.title("Распределение счетов по дням недели", fontsize=18, pad=20)
plt.xlabel("День недели", fontsize=14, labelpad=15)
plt.ylabel("Сумма счета ($)", fontsize=14, labelpad=15)

# Улучшение сетки для читаемости
plt.grid(axis='y', alpha=0.3, linestyle='--')

# Настройка тиков осей
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)

# Добавление аннотаций
medians = tips.groupby('day')['total_bill'].median().values
positions = range(len(medians))
for pos, median in zip(positions, medians):
plt.text(pos, median+1, f"${median:.2f}", horizontalalignment='center', 
size='medium', color='darkblue', weight='semibold')

plt.tight_layout()
plt.show()

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

Python
Скопировать код
# Создание более сложного Violin Plot с подгруппами
plt.figure(figsize=(14, 8))

# Основной график с разделением по двум категориям
vp = sns.violinplot(x="day", y="total_bill", hue="time", data=tips, 
split=True, inner="quartile", palette={"Lunch": "#9b59b6", "Dinner": "#3498db"},
linewidth=1.2, cut=0)

# Добавление swarmplot для отображения фактических точек данных
sns.swarmplot(x="day", y="total_bill", hue="time", data=tips,
size=4, edgecolor="gray", linewidth=0.5, 
palette={"Lunch": "#d2b4de", "Dinner": "#aed6f1"}, 
dodge=True, alpha=0.7)

# Улучшение легенды
handles, labels = vp.get_legend_handles_labels()
plt.legend(handles[:2], labels[:2], title="Время приема пищи", 
loc="upper right", frameon=True, fontsize=12)

# Настройка осей и заголовков
plt.title("Распределение счетов по дням недели и времени приема пищи", 
fontsize=18, pad=20)
plt.xlabel("День недели", fontsize=14, labelpad=15)
plt.ylabel("Сумма счета ($)", fontsize=14, labelpad=15)

# Персонализация стиля графика
plt.grid(axis='y', alpha=0.3, linestyle='-.')
sns.despine(left=False, bottom=False)

plt.tight_layout()
plt.show()

Для создания высокоинформативных и стилизованных Violin Plot с добавлением статистической информации:

Python
Скопировать код
# Создание Violin Plot со статистическими элементами
plt.figure(figsize=(14, 10))

# Измененный формат основного графика
vp = sns.violinplot(x="day", y="total_bill", data=tips, inner=None, 
palette="YlGnBu", cut=0, width=0.8)

# Наложение boxplot для отображения статистических параметров
sns.boxplot(x="day", y="total_bill", data=tips, width=0.15, 
color="white", boxprops={"zorder": 2}, showfliers=False)

# Добавление фактических точек данных с jitter
sns.stripplot(x="day", y="total_bill", data=tips, size=3, 
color=".3", linewidth=0, alpha=0.4, jitter=True)

# Расчет и отображение статистик
for i, day in enumerate(tips['day'].unique()):
day_data = tips[tips['day'] == day]['total_bill']

# Среднее значение
plt.text(i, day_data.mean()+1, f"μ={day_data.mean():.2f}", 
horizontalalignment='center', size=11, color='darkgreen')

# Медиана уже показана в boxplot

# Стандартное отклонение
plt.text(i, day_data.max()+2, f"σ={day_data.std():.2f}", 
horizontalalignment='center', size=11, color='darkred')

# Улучшение внешнего вида
plt.title("Расширенный анализ распределения счетов по дням недели", 
fontsize=18, pad=20)
plt.xlabel("День недели", fontsize=14, labelpad=15)
plt.ylabel("Сумма счета ($)", fontsize=14, labelpad=15)

# Добавление подписи и пояснительного текста
plt.figtext(0.15, 0.01, "Примечание: μ – среднее значение, σ – стандартное отклонение", 
fontsize=10, style='italic')

plt.tight_layout(pad=2)
plt.show()

Дополнительные советы по стилизации для профессиональных презентаций:

  • Используйте согласованные цветовые схемы, соответствующие вашему бренду или теме презентации
  • Для научных публикаций выбирайте цветовые палитры, которые хорошо воспроизводятся при печати в оттенках серого
  • Добавляйте информативные подписи, пояснения и аннотации прямо на графике
  • Для сравнения нескольких категорий используйте цветовые градиенты вместо ярко контрастирующих цветов
  • Сохраняйте графики в векторных форматах (SVG, PDF) для презентаций высокого качества

Мария Соколова, руководитель отдела аналитики

Подготовка отчета для руководства о влиянии нового образовательного продукта на результаты студентов поставила перед нами серьезный вызов. У нас были данные по тестовым баллам, но стандартные столбчатые диаграммы средних значений не передавали полной картины. Решение пришло с Violin Plot — я создала сравнительную визуализацию, где контрольная и экспериментальная группы были представлены рядом. График наглядно показывал не только улучшение средних показателей, но и важнейший факт: новая методика особенно помогала отстающим студентам. Руководство, увидев эту визуализацию, моментально поняло ценность продукта и утвердило масштабное внедрение методики. Violin Plot превратил сложные статистические данные в четкую историю успеха, понятную даже нетехническим специалистам.

Сравнительный анализ распределений с Violin Plot

Одно из главных преимуществ Violin Plot — возможность наглядного сравнения распределений между различными группами данных. Это особенно полезно при проведении А/Б-тестирования, сравнении демографических групп или анализе изменений во времени. 📈

Рассмотрим методы эффективного построения сравнительных Violin Plot для выявления различий в распределениях:

Python
Скопировать код
# Загрузка датасета для демонстрации
diamonds = sns.load_dataset("diamonds")

# Подготовка данных для сравнения (выборка для ускорения визуализации)
diamonds_sample = diamonds.sample(n=3000, random_state=42)

# Сравнение распределения цен бриллиантов по качеству огранки
plt.figure(figsize=(14, 8))

# Основной Violin Plot
sns.violinplot(x="cut", y="price", data=diamonds_sample, 
palette="viridis", inner="quartile", 
order=["Fair", "Good", "Very Good", "Premium", "Ideal"])

# Настройка графика
plt.title("Распределение цен бриллиантов по качеству огранки", fontsize=16)
plt.xlabel("Качество огранки", fontsize=14)
plt.ylabel("Цена (USD)", fontsize=14)
plt.grid(axis='y', linestyle='--', alpha=0.7)

plt.show()

Для более детального сравнения можно добавить статистические тесты:

Python
Скопировать код
from scipy import stats
import numpy as np

# Функция для расчета и отображения результатов статистических тестов
def add_statistical_comparison(ax, data, x_var, y_var, pairs):
# Получение уникальных категорий и их позиций
categories = data[x_var].unique()
positions = dict(zip(categories, range(len(categories))))

# Высота для размещения скобок сравнения
y_max = data[y_var].max()

for i, (group1, group2) in enumerate(pairs):
# Получение данных для каждой группы
data1 = data[data[x_var] == group1][y_var]
data2 = data[data[x_var] == group2][y_var]

# Выполнение t-теста
t_stat, p_value = stats.ttest_ind(data1, data2, equal_var=False)

# Определение высоты для текущего сравнения
height = y_max + (i + 1) * (y_max * 0.05)

# Добавление скобки и p-value
x1, x2 = positions[group1], positions[group2]
plt.plot([x1, x1, x2, x2], [height-y_max*0.02, height, height, height-y_max*0.02], 
lw=1.5, c='black')

# Форматирование p-value для отображения
if p_value < 0.001:
p_text = "p < 0.001 ***"
elif p_value < 0.01:
p_text = f"p = {p_value:.3f} **"
elif p_value < 0.05:
p_text = f"p = {p_value:.3f} *"
else:
p_text = f"p = {p_value:.3f} (ns)"

plt.text((x1+x2)/2, height+y_max*0.01, p_text, ha='center', va='bottom', fontsize=12)

# Создание основного графика
plt.figure(figsize=(16, 10))
ax = sns.violinplot(x="cut", y="price", data=diamonds_sample, 
palette="viridis", inner="quartile", 
order=["Fair", "Good", "Very Good", "Premium", "Ideal"])

# Добавление статистических сравнений
pairs_to_compare = [("Fair", "Good"), ("Good", "Very Good"), 
("Very Good", "Premium"), ("Premium", "Ideal")]
add_statistical_comparison(ax, diamonds_sample, "cut", "price", pairs_to_compare)

# Настройка графика
plt.title("Статистическое сравнение цен бриллиантов по качеству огранки", fontsize=16)
plt.xlabel("Качество огранки", fontsize=14)
plt.ylabel("Цена (USD)", fontsize=14)
plt.ylim(0, diamonds_sample["price"].max() * 1.3) # Расширение для аннотаций
plt.grid(axis='y', linestyle='--', alpha=0.7)

# Пояснение к уровням значимости
plt.figtext(0.15, 0.01, "Уровни значимости: *** p<0.001, ** p<0.01, * p<0.05, ns – не значимо", 
fontsize=10, style='italic')

plt.tight_layout()
plt.show()

Для двумерного сравнения с дополнительной группировкой:

Python
Скопировать код
# Сравнение распределения цен по огранке и прозрачности
plt.figure(figsize=(18, 10))

# Фильтрация датасета для четкой визуализации
clarity_order = ["I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"]
cut_order = ["Fair", "Good", "Very Good", "Premium", "Ideal"]

# Создание основного графика с двумя факторами
sns.violinplot(x="clarity", y="price", hue="cut", data=diamonds_sample,
palette="YlOrBr", split=False, inner="quartile", 
order=clarity_order, hue_order=cut_order,
scale="width", gridsize=100)

# Улучшение читаемости визуализации
plt.title("Сравнительный анализ цен бриллиантов по прозрачности и качеству огранки", fontsize=16)
plt.xlabel("Прозрачность", fontsize=14)
plt.ylabel("Цена (USD)", fontsize=14)
plt.legend(title="Качество огранки", fontsize=12, title_fontsize=13)
plt.grid(axis='y', linestyle='--', alpha=0.4)

# Поворот подписей x-оси для лучшей читаемости
plt.xticks(rotation=45)

plt.tight_layout()
plt.show()

Ключевые методики для эффективного сравнительного анализа с помощью Violin Plot:

Тип сравненияМетодикаКогда использовать
Простое сравнение группБазовый violinplot с упорядоченными категориямиПри сравнении до 7-8 групп с одномерными данными
Попарное сравнение со статистикойViolinplot + статистические тесты с аннотациямиДля научных публикаций, требующих строгих статистических доказательств
Многофакторное сравнениеViolinplot с параметром hue для группировкиПри анализе взаимодействия двух категориальных переменных
До/После сравнениеПарные violinplot с разделенной осьюПри анализе изменений в эксперименте, А/Б-тестировании
Многомерное сравнениеМатрица violinplot (FacetGrid)При необходимости сравнения по трем и более измерениям

Для создания матрицы сравнительных Violin Plot:

Python
Скопировать код
# Создание матрицы Violin Plot для многомерного сравнения
g = sns.FacetGrid(diamonds_sample, col="color", row="cut", 
margin_titles=True, height=3, aspect=1.2,
col_order=["D", "E", "F", "G", "H", "I", "J"],
row_order=["Ideal", "Premium", "Very Good", "Good", "Fair"])

# Определение функции построения для каждой ячейки
g.map(sns.violinplot, "clarity", "price", inner=None, order=clarity_order, 
palette="mako", cut=0, linewidth=1)

# Добавление индивидуальных точек для малых выборок
g.map(sns.stripplot, "clarity", "price", size=2, color=".3", 
linewidth=0, alpha=0.5, jitter=True)

# Настройка общих заголовков и подписей
g.set_axis_labels("Прозрачность", "Цена (USD)")
g.set_titles(col_template="Цвет: {col_name}", row_template="Огранка: {row_name}")
g.fig.suptitle("Многомерный анализ цен бриллиантов", fontsize=18)
g.fig.subplots_adjust(top=0.93)

# Поворот подписей оси x
for ax in g.axes.flat:
ax.set_xticklabels(ax.get_xticklabels(), rotation=45)

plt.tight_layout()
plt.show()

Хотите определить, какое направление в аналитике лучше всего подходит для ваших навыков и интересов? Тест на профориентацию от Skypro поможет вам понять, стоит ли развиваться в области визуальной аналитики данных или ваши таланты лежат в другой сфере. Пройдите короткий онлайн-тест и получите персональные рекомендации по карьерному развитию, включая оценку ваших способностей к работе с такими инструментами как Violin Plot и другими методами визуализации данных.

Практические кейсы применения Violin Plot в исследованиях

Violin Plot находит широкое применение в различных областях исследований, от научных экспериментов до бизнес-аналитики. Рассмотрим несколько практических кейсов с реализацией в Python. 🔬

  1. Фармацевтические исследования: анализ эффективности препаратов
Python
Скопировать код
# Синтетические данные для демонстрации
np.random.seed(42)
drug_data = pd.DataFrame({
'Drug': np.repeat(['A', 'B', 'C', 'Placebo'], 50),
'Response': np.concatenate([
np.random.normal(30, 5, 50), # Препарат A
np.random.normal(25, 7, 50), # Препарат B
np.random.normal(40, 4, 50), # Препарат C
np.random.normal(20, 6, 50) # Плацебо
]),
'Age_Group': np.random.choice(['18-30', '31-45', '46-60', '60+'], 200)
})

# Создание расширенного Violin Plot
plt.figure(figsize=(14, 8))

# Основной график с цветовым кодированием по возрастным группам
ax = sns.violinplot(x="Drug", y="Response", hue="Age_Group", data=drug_data, 
palette="rocket", inner="quartile", split=False)

# Наложение точек данных для детального рассмотрения
sns.stripplot(x="Drug", y="Response", hue="Age_Group", data=drug_data, 
dodge=True, alpha=0.3, jitter=True, size=4, linewidth=1, 
palette="rocket")

# Устранение дублирования в легенде
handles, labels = ax.get_legend_handles_labels()
plt.legend(handles[:4], labels[:4], title="Возрастная группа", 
bbox_to_anchor=(1.05, 1), loc='upper left')

# Добавление статистической информации о средних значениях
for i, drug in enumerate(drug_data['Drug'].unique()):
mean_val = drug_data[drug_data['Drug'] == drug]['Response'].mean()
plt.text(i, mean_val + 2, f"μ = {mean_val:.1f}", 
ha='center', va='bottom', fontsize=12, weight='bold')

# Настройка внешнего вида
plt.title("Сравнение эффективности препаратов по возрастным группам", fontsize=16)
plt.xlabel("Препарат", fontsize=14)
plt.ylabel("Клинический ответ (единицы измерения)", fontsize=14)
plt.grid(axis='y', linestyle='--', alpha=0.5)

plt.tight_layout()
plt.show()
  1. Финансовый анализ: распределение доходности различных инвестиционных инструментов
Python
Скопировать код
# Синтетические данные о доходности инвестиций
np.random.seed(42)
investments = pd.DataFrame({
'Type': np.repeat(['Stocks', 'Bonds', 'Real_Estate', 'Crypto', 'Commodities'], 100),
'Return': np.concatenate([
np.random.normal(8, 15, 100), # Акции
np.random.normal(4, 3, 100), # Облигации
np.random.normal(6, 5, 100), # Недвижимость
np.concatenate([ # Криптовалюта (бимодальное распределение)
np.random.normal(20, 10, 50), 
np.random.normal(-10, 15, 50)
]),
np.random.normal(5, 8, 100) # Сырьевые товары
]),
'Year': np.random.choice(['2021', '2022', '2023', '2024', '2025'], 500)
})

# Расчет статистики рисков
risk_stats = investments.groupby('Type')['Return'].agg(['std', 'mean', 'median', 
lambda x: np.percentile(x, 10),
lambda x: np.percentile(x, 90)])
risk_stats.columns = ['Волатильность', 'Средняя доходность', 'Медиана', 'P10', 'P90']
risk_stats['Коэф. Шарпа'] = risk_stats['Средняя доходность'] / risk_stats['Волатильность']
risk_stats = risk_stats.sort_values('Коэф. Шарпа', ascending=False)

# Создание визуализации
plt.figure(figsize=(15, 10))

# Основной график
order = risk_stats.index
sns.violinplot(x="Type", y="Return", data=investments, inner="quartile", 
palette="Blues", order=order, cut=0)

# Добавление горизонтальной линии на уровне нулевой доходности
plt.axhline(y=0, color='red', linestyle='--', alpha=0.7)

# Аннотации с ключевыми рисковыми метриками
for i, typ in enumerate(order):
stats = risk_stats.loc[typ]
plt.annotate(f"Волат: {stats['Волатильность']:.1f}\nШарп: {stats['Коэф. Шарпа']:.2f}", 
xy=(i, stats['P90'] + 2), xytext=(i, stats['P90'] + 5),
ha='center', va='bottom', fontsize=10,
bbox=dict(boxstyle="round,pad=0.3", fc='white', ec="gray", alpha=0.8))

# Настройка внешнего вида
plt.title("Распределение доходности по типам инвестиций (2021-2025)", fontsize=16)
plt.xlabel("Тип инвестиций", fontsize=14)
plt.ylabel("Годовая доходность (%)", fontsize=14)
plt.grid(axis='y', linestyle='--', alpha=0.5)

# Улучшение читаемости оси x
plt.xticks([0, 1, 2, 3, 4], ['Акции', 'Облигации', 'Недвижимость', 
'Криптовалюта', 'Сырьевые товары'], rotation=0)

plt.tight_layout()
plt.show()
  1. Образовательная аналитика: анализ результатов студентов до и после внедрения новых методик обучения
Python
Скопировать код
# Синтетические данные об успеваемости
np.random.seed(42)
n_students = 200
student_data = pd.DataFrame({
'Student_ID': range(1, n_students + 1),
'Group': np.repeat(['Control', 'Experimental'], n_students // 2),
'Score_Before': np.concatenate([
np.random.normal(65, 15, n_students // 2), # Контрольная группа
np.random.normal(63, 14, n_students // 2) # Экспериментальная группа
]),
})

# Создание результатов после эксперимента с различным эффектом
control_after = student_data[student_data['Group'] == 'Control']['Score_Before'] + np.random.normal(5, 5, n_students // 2)
experimental_after = student_data[student_data['Group'] == 'Experimental']['Score_Before'] + np.random.normal(15, 8, n_students // 2)

student_data['Score_After'] = np.concatenate([control_after, experimental_after])

# Преобразование в "длинный" формат для визуализации
student_long = pd.melt(student_data, 
id_vars=['Student_ID', 'Group'],
value_vars=['Score_Before', 'Score_After'],
var_name='Time', value_name='Score')

student_long['Time'] = student_long['Time'].str.replace('Score_', '')

# Создание визуализации
plt.figure(figsize=(14, 9))

# Основной график
sns.violinplot(x="Group", y="Score", hue="Time", data=student_long, 
split=True, inner="quart", palette={"Before": "#3498db", "After": "#2ecc71"},
cut=0)

# Добавление линий, соединяющих средние значения
for group in ['Control', 'Experimental']:
group_data = student_long[student_long['Group'] == group]
mean_before = group_data[group_data['Time'] == 'Before']['Score'].mean()
mean_after = group_data[group_data['Time'] == 'After']['Score'].mean()

idx = 0 if group == 'Control' else 1
plt.plot([idx-0.2, idx+0.2], [mean_before, mean_after], color='black', 
linestyle='-', linewidth=2, marker='o', markersize=8)

# Добавление аннотации об улучшении
improvement = mean_after – mean_before
plt.annotate(f"+{improvement:.1f}", xy=(idx, (mean_before + mean_after)/2 + 2),
xytext=(idx + 0.35, (mean_before + mean_after)/2 + 2),
arrowprops=dict(arrowstyle='->'), fontsize=12, fontweight='bold',
color='darkgreen' if improvement > 10 else 'black')

# Настройка внешнего вида
plt.title("Влияние новой методики обучения на результаты студентов", fontsize=16)
plt.xlabel("Группа", fontsize=14)
plt.ylabel("Тестовый балл", fontsize=14)
plt.grid(axis='y', linestyle='--', alpha=0.5)
plt.ylim(20, 110)

# Добавление аннотации с описанием результатов
plt.figtext(0.15, 0.01, 
"Экспериментальная группа показала значительно более высокое улучшение показателей\n" +
"по сравнению с контрольной группой, что подтверждает эффективность новой методики.", 
fontsize=12)

plt.tight_layout()
plt.show()

Другие области практического применения Violin Plot:

  • Биомедицинские исследования: анализ экспрессии генов, сравнение биомаркеров между группами пациентов
  • Социологические исследования: визуализация распределения мнений по разным демографическим группам
  • Инженерный анализ: сравнение производительности различных систем или конфигураций
  • Экологические исследования: анализ распределения биологических показателей в разных экосистемах
  • Маркетинговые исследования: сравнение потребительских предпочтений между сегментами рынка
  • Спортивная аналитика: сравнение распределения показателей производительности спортсменов
  • Психологические исследования: анализ распределения результатов психологических тестов

Violin Plot — это не просто визуальный инструмент, а мощный способ глубокого понимания данных, который превосходит традиционные методы визуализации. Объединяя в себе лучшие качества box plot и плотностного распределения, скрипичные диаграммы позволяют аналитикам одновременно видеть центральные тенденции, вариативность, форму распределения и выбросы. Эта многогранность делает их незаменимыми при сравнительном анализе групп, выявлении неоднородностей в данных и поиске скрытых закономерностей. Владение этим инструментом — признак профессионального аналитика, способного извлечь максимум информации из своих данных.