Original size 960x1280

Эффективность ваших тренировок

PROTECT STATUS: not protected

Введение.

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

Данные я искала на платформе Kaggle и решила остановиться на датасете «Gym Members Exercise Dataset», содержащий подробную информацию о 973 тренировках — от физиологических показателей (ЧСС, калории, % жира) до поведенческих (тип тренировки, частота, длительность, гидратация).

В этом проекте я решила исследовать, какие факторы действительно влияют на эффективность тренировки. Цель — найти закономерности, которые помогут сделать тренировки умнее, безопаснее и результативнее.

Поскольку меня заинтересовал этот проект, я решила подробнее углубиться в способы визуализации и анализа данных и дополнительно изучила курс на stepik по библиотеке matplotlib «Визуализация с Matplotlib для анализа данных» и документацию по библиотекам matplotlib, seaborn, numpy, pandas.

Ссылка на копию ноутбука с кодом: https://colab.research.google.com/drive/1L3N8pEg2tLE09fTxX6ZHAkJKmge-NpQo

Коррелограмма.

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

Чтобы визуализировать все попарные корреляции сразу, я построила тепловую карту —коррелограмму. Чтобы избежать дублирования и улучшить читаемость, отображена только нижняя треугольная часть матрицы: диагональ (где каждый признак коррелирует сам с собой, r=1) и зеркальные значения исключены как избыточные.

data_corr = data[num_cols].corr ().round (2) mask = np.triu (np.ones_like (data_corr, dtype=bool)) # Приводим к нижнетреугольной матрице

plt.figure (figsize=(10, 8)) heatmap = sns.heatmap ( data_corr, mask=mask, annot=True, fmt=».2f», cmap='coolwarm', square=True, linewidths=0.6, linecolor='#E0E0E0') heatmap.set_facecolor ('#FAFAFA') heatmap.tick_params (axis='x', rotation=45, colors='#333333', labelsize=9) heatmap.tick_params (axis='y', rotation=0, colors='#333333', labelsize=9)

plt.title ('Коррелограмма', fontsize=14, pad=20, fontweight='bold', color='#222222') plt.tight_layout () plt.show ()

Original size 890x790

Анализ зависимостей признаков с высокой корреляцией.

Важно помнить, что высокая корреляция не гарантирует наличия реальной линейной зависимости, а также не учитывает возможные выбросы, нелинейные тренды или смещения в распределении. Поэтому я не ограничилась числами — для всех пар признаков с коэффициентом корреляции выше 0.5 я построила диаграммы рассеяния (scatter plots).

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

Такую же отчетливую зависимость мы можем наблюдать между весом и индексом массы тела человека (BMI), потому что BMI вычисляется как вес, деленный на квадрат роста. Поскольку рост в выборке варьируется меньше, чем вес, основной вклад в изменение BMI вносит именно масса тела.

Отрицательная корреляция между количеством сожженых калорий и процентом жира человека тоже согласуется с ожиданиями: регулярные тренировки способствуют снижению жировой массы, особенно в сочетании с контролем питания. Однако важно помнить: корреляция не означает причинно-следственную связь — возможно, люди с уже низким % жира просто чаще и интенсивнее тренируются.

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

Особый интерес вызывает распределение на графике зависимости длительности тренировки от процента жира: точки словно формируют две обособленные группы. Чтобы понять, что стоит за этим паттерном, я разделила участников на три категории по уровню жировой массы — низкий, средний и высокий — и построила точечную диаграмму с расслоением (strip plot) для более детального сравнения.

data['Fat_Group'] = pd.cut (data['Fat_Percentage'], bins=[0, 15, 25, 100], labels=['Низкий', 'Норма', 'Высокий']) plt.figure (figsize=(10, 6)) ax = plt.gca () ax.set_facecolor ('#FAFAFA') plt.gcf ().set_facecolor ('white') ax.grid (axis='y', linestyle='--', linewidth=0.6, color='#CCCCCC', alpha=0.5)

sns.stripplot ( data=data, x='Fat_Group', y='Session_Duration', jitter=0.25, alpha=0.6, size=5, palette=['

609AC9', '

669DAD', '#567EB9'])

medians = data.groupby ('Fat_Group')['Session_Duration'].median () for i, (group, med) in enumerate (medians.items ()): plt.hlines (med, i — 0.3, i + 0.3, color='black', linestyle='--', linewidth=1.2)

plt.xlabel ('Группа по % жира') plt.ylabel ('Длительность тренировки (часы)') plt.title ('Длительность тренировки и процент жира', fontweight='bold', fontsize=16) sns.despine () plt.tight_layout () plt.show ()

Original size 989x590

Люди с низким процентом жира в среднем демонстрируют более длительные тренировки, в то время как среди участников с высоким процентом жира наблюдается как группа с умеренной длительностью, так и заметное количество лиц с короткими сессиями (около 0.5 часа). Это может указывать на то, что регулярные и продолжительные тренировки ассоциированы с более низким уровнем жировой массы — либо как причина, либо как следствие более вовлечённого подхода к фитнесу.

Сжигают ли женщины и мужчины калории одинаково?

Мне стало интересно, действительно ли мужчины и женщины по-разному расходуют энергию при одинаковой нагрузке, и чтобы это понять я построила диаграмму рассеяния с линиями линейной регрессии, раздельно для каждого пола.

На графике по оси X отложена длительность тренировки, по оси Y — количество сожжённых калорий. Голубым цветом обозначены мужчины, а розовым — женщины. Линии регрессии позволяют оценить среднюю эффективность (наклон линии = калории в час) и сравнить её между группами.

gender_palette = { 'Male': '#609AC9', 'Female': '#B97FB9' } line_colors = { 'Male': '#406A8D', 'Female': '#7B4B7C' }

g = sns.lmplot (data=data, x='Session_Duration', y='Calories_Burned', hue='Gender', palette=gender_palette, height=6, aspect=1.2, scatter_kws={'alpha': 0.6, 's': 50, 'edgecolor': 'gray'}, line_kws={'linewidth': 3}, legend=False )

for i, gender in enumerate (['Male', 'Female']): g.ax.get_lines ()[i].set_color (line_colors[gender])

g.ax.set_facecolor ('#FAFAFA') g.ax.grid (True, linestyle='--', alpha=0.3) sns.despine () g.set_axis_labels ('Длительность тренировки (часы)', 'Сожжённые калории') g.fig.suptitle ('Сравнение эффективности тренировок по полу', fontsize=16, fontweight='bold')

handles = [ plt.Line2D ([0], [0], marker='o', color='w', markerfacecolor=gender_palette[gender], markersize=8, markeredgecolor='gray', linestyle='None', label='Мужчины' if gender == 'Male' else 'Женщины') for gender in ['Male', 'Female'] ] g.ax.legend ( handles=handles, title='Пол', loc='lower right', frameon=True, facecolor='#FAFAFA', framealpha=0.95 )

plt.tight_layout () plt.show ()

Original size 709x592

Как мы видим, наклоны линий различаются — при одинаковом времени тренировки мужчины в среднем сжигают больше калорий, нежели женщины.

В целом это объясняется физиологическими особенностями: у мужчин, как правило, выше мышечная масса и ниже процент жира, а мышечная ткань — метаболически активна, даже в покое. Следовательно, при одинаковой нагрузке их организм тратит больше энергии.

Насколько % жира зависит от уровня спортивной подготовки для разных полов?

Чтобы понять, как уровень спортивной подготовки влияет на состав тела, я исследую распределение процента жира отдельно для мужчин и женщин на разных этапах фитнес-пути: от новичков (уровень 1) до опытных спортсменов (уровень 3).

Для визуализации я выбрала точечные диаграммы с наложением кривых плотности (strip plots с KDE), потому что они позволяют сравнивать формы распределений, а не только средние значения, кривая плотности (она же KDE) показывает, где сосредоточена основная масса данных (аналог гистограммы, но без зависимости от числа корзин). Это особенно важно, когда группы имеют разный размер — плотность нормирована на единицу площади, поэтому сравнение остаётся корректным.

Такой подход помогает увидеть не только средний сдвиг (% жира снижается с опытом), но и изменение разброса и формы распределения — например, становится ли состав тела более однородным у продвинутых атлетов.

levels = [1, 2, 3] gender_colors_fill = {'Male': '

609AC9', 'Female': '

B97FB9'} gender_colors_kde = {'Male': '

406A8D', 'Female': '

7B4B7C'}

fig, axes = plt.subplots (1, 3, figsize=(12, 5), sharex=True, sharey=True) fig.suptitle ('Распределение процента жира по уровню подготовки', fontsize=16, fontweight='bold')

for i, level in enumerate (levels): ax = axes[i] data_level = data[data['Experience_Level'] == level]

# Гистограмма в шкале плотности
for gender in ['Male', 'Female']:
    subset = data_level[data_level['Gender'] == gender]['Fat_Percentage']
    sns.histplot (subset, bins=15, stat='density', alpha=0.6, color=gender_colors_fill[gender], kde=False, ax=ax)

# 2. Добавляем кривые KDE
for gender in ['Male', 'Female']:
    subset = data_level[data_level['Gender'] == gender]['Fat_Percentage']
    sns.kdeplot (subset, color=gender_colors_kde[gender], linewidth=2.5, ax=ax)

ax.set_title (f’Уровень подготовки: {level}')
ax.set_facecolor ('#FAFAFA')
ax.grid (axis='y', linestyle='--', alpha=0.4)
sns.despine (ax=ax)
if i == 0:
    ax.set_ylabel ('Относительная частота')
else:
    ax.set_ylabel ('')

fig.text (0.5, 0.02, 'Процент жира (%)', ha='center', fontsize=12)

handles = [ plt.Rectangle ((0, 0), 1, 1, color=gender_colors_fill['Male'], alpha=0.6), plt.Rectangle ((0, 0), 1, 1, color=gender_colors_fill['Female'], alpha=0.6) ] fig.legend (handles, ['Мужчины', 'Женщины'], title='Пол', loc='lower left', bbox_to_anchor=(0.7, 0.02), ncol=2, shadow=True)

plt.tight_layout (rect=[0.02, 0.12, 0.98, 0.92]) plt.show ()

Original size 1142x504

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

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

Какой тип тренировок самый эффективный для сжигания жира?

Одна из главных целей фитнес-тренировок — снижение жировой массы. Чтобы оценить эффективность разных видов нагрузки, я рассчитала среднее количество калорий, сжигаемых за час (Calories_Burned / Session_Duration) для каждого типа тренировки и визуализировала результаты в виде горизонтальной столбчатой диаграммы (barh). Этот тип графика позволяет легко сравнивать значения между категориями и сразу видеть лидера по эффективности.

Попробуем еще поизучать различия в типах тренировок: для этого я построила четыре графика boxplot (так называемые «ящики с усами») по ключевым метрикам: сожжённые калории, средняя ЧСС (частота сердечных сокращений, интенсивность), длительность сессии, эффективность (ккал/час).

Boxplot’ы позволяют увидеть не только средние значения, но и полное распределение данных: разброс, наличие выбросов, асимметрию. Это особенно важно, когда средние могут вводить в заблуждение — например, из-за небольшого числа аномально длинных йога-сессий.

efficiency = data.groupby ('Workout_Type')['Calories_Per_Hour'].mean ().sort_values ()

color_map = { 'Cardio': '#91B7D6', 'Strength': '#609AC9', 'Yoga': '#567EB9', 'HIIT': '#669DAD' }

colors = [color_map[w] for w in efficiency.index]

plt.figure (figsize=(8, 4)) bars = plt.barh (efficiency.index, efficiency.values, color=colors)

for i, (workout, value) in enumerate (efficiency.items ()): plt.text (value + 10, i, f'{value:.0f} кал/ч', va='center', fontsize=11, color='#333333')

plt.xlabel ('Среднее количество калорий в час') plt.title ('Эффективность тренировок по сжиганию калорий', fontweight='bold', fontsize=16) sns.despine (left=True) plt.tight_layout () plt.show ()

Original size 789x390

color_map = { 'Cardio': '#91B7D6', 'Strength': '#609AC9', 'Yoga': '#567EB9', 'HIIT': '#669DAD' } metrics = ['Water_Intake', 'Avg_BPM', 'Session_Duration', 'Calories_Per_Hour'] titles = [ 'Потребление воды (л/день)', 'Средняя ЧСС (уд/мин)', 'Длительность тренировки (ч)', 'Эффективность тренировок (кал/ч)' ]

fig, axes = plt.subplots (2, 2, figsize=(10, 7)) axes = axes.flatten () fig.suptitle ('Влияние типа тренировки на основные показатели', fontsize=16, fontweight='bold')

for i, (metric, title) in enumerate (zip (metrics, titles)): ax = axes[i] sns.boxplot (data=data, x='Workout_Type', y=metric, ax=ax, palette=color_map, width=0.6, linewidth=1.2) ax.set_title (title, fontsize=13, fontweight='bold', pad=12) ax.set_xlabel ('') ax.set_ylabel ('') ax.set_facecolor ('#FAFAFA') ax.grid (True, linestyle='--', linewidth=0.5, alpha=0.4)

fig.text (0.5, 0.02, 'Тип тренировки', ha='center', fontsize=12) fig.text (0.02, 0.5, 'Значение показателя', va='center', rotation='vertical', fontsize=12)

plt.tight_layout (rect=[0.03, 0.03, 1, 1]) plt.show ()

Эффективность ваших тренировок
Project created at 17.01.2026
We use cookies to improve the operation of the HSE website and to enhance its usability. More detailed information on the use of cookies can be fou...
Show more