Описание проекта
В данном проекте рассматривается датасет Weight–Height, содержащий данные о росте, весе и поле людей. Цель анализа — изучить взаимосвязь между ростом и весом, а также выявить различия в распределениях этих показателей у мужчин и женщин. Для исследования были использованы методы описательной статистики и визуализации данных, позволяющие наглядно представить структуру распределений и характер зависимости между переменными. В работе использован датасет Weight–Height — набор данных, содержащий информацию о поле, росте и весе людей. Датасет был найден на платформе Kaggle и представляет собой чистую таблицу с количественными переменными, удобную для анализа и визуализации. Переменные датасета:
- Gender — пол (мужчины / женщины),
- Height — рост,
- Weight — вес.
Этот датасет показался мне интересным по нескольким причинам:
- Он интуитивно понятен и связан с реальными физическими характеристиками человека.
- В нём есть как непрерывные количественные переменные, так и категориальная переменная (пол), что позволяет сравнивать группы.
- Данные хорошо подходят для демонстрации базовых приёмов анализа данных: распределений, зависимостей, групповых сравнений и проверки статистических гипотез.
- Несмотря на простоту, датасет позволяет показать разницу между визуальным и статистическим анализом. Для анализа были выбраны разные типы визуализаций, каждая из которых решает свою задачу:
- Scatter plot (точечные диаграммы) Используются для анализа зависимости веса от роста и выявления общей тенденции.
- Линейные тренды (линии регрессии) Добавлены для наглядного отображения направления и силы связи между ростом и весом.
- Гистограммы распределений Позволяют сравнить форму распределения роста и веса у мужчин и женщин.
- Гистограммы с наложением (мужчины и женщины на одном графике) Используются для прямого визуального сравнения групп.
- Агрегированный график по интервалам роста Показывает, как меняется средний вес при фиксированном росте, что делает сравнение более корректным.
Этапы работы
Этап 1. Загрузка и первичный просмотр данных
import pandas as pd
df = pd.read_csv("weight-height.csv") df.head() df.info()
На этом этапе я изучила структуру таблицы, типы переменных и убедилась, что данные подходят для анализа.
Этап 2. Очистка и подготовка данных
Основные шаги обработки:
- удаление пропусков,
- приведение роста и веса к числовому типу,
- стандартизация значений пола.
df.columns = df.columns.str.strip() df["Height"] = pd.to_numeric(df["Height"], errors="coerce") df["Weight"] = pd.to_numeric(df["Weight"], errors="coerce") df = df.dropna(subset=["Gender", "Height", "Weight"])
df["gender_norm"] = df["Gender"].str.lower().apply( lambda x: "Male" if x.startswith("m") else "Female" )
В данном проекте нейросети не использовались. Все этапы анализа и визуализации были выполнены с помощью стандартных библиотек Python: pandas, numpy, matplotlib.
Стилизация графиков
Для всех визуализаций была использована единая цветовая система, чтобы графики выглядели как часть одного проекта:
- бордовый — мужчины,
- золотой — женщины,
- тёплый светлый фон,
- единые сетка, шрифты и подписи.
Это позволило создать визуально цельную инфографику и повысить читаемость графиков.
Изучающий и объясняющий формат визуализации
Графики были построены так, чтобы не просто показывать данные, но и объяснять их:
- добавлены линии среднего значения и стандартного отклонения;
- использованы подписи и легенды;
- показаны тренды и агрегированные значения;
- визуализации выстроены от общего обзора к более детальному сравнению групп.
Используемые статистические методы
В работе применялись следующие методы:
Описательная статистика Среднее значение, стандартное отклонение, форма распределения.
Корреляционный анализ Оценка связи между ростом и весом.
Линейная регрессия (polyfit) Для построения трендов зависимости веса от роста.
Групповая агрегация данных Средние и стандартные отклонения по полу и по интервалам роста.
Палитра
График 1
График 1. Зависимость веса от роста
Показывает общую связь между ростом и весом и наличие линейного тренда.
--- scatter: вес от роста по полу + тренды ---
fig, ax = plt.subplots(figsize=(10, 6)) ax.scatter(m[h], m[w], s=14, alpha=0.35, color=C_M, label="Мужчины") ax.scatter(f[h], f[w], s=14, alpha=0.35, color=C_G, label="Женщины")
for data, col in [(m, C_M), (f, C_F)]: k, b = np.polyfit(data[h], data[w], 1) xx = np.linspace(df[h].min(), df[h].max(), 200) ax.plot(xx, k*xx + b, color=col, linewidth=2.5)
ax.set_title("Зависимость веса от роста по полу") ax.set_xlabel("Рост"); ax.set_ylabel("Вес") ax.legend(frameon=True, facecolor="#FFFDF8", edgecolor=GRID) plt.tight_layout(); plt.show()
График 2
График 2. Зависимость веса от роста по полу
Позволяет сравнить мужчин и женщин и увидеть различия в средних значениях при одинаковом росте.
fig, ax = plt.subplots(figsize=(10, 6))
данные
data_m = m[h] data_f = f[h] COL_EDGE = "
1E434C"
тёмный контур / осигистограммы (нормированные, чтобы корректно сравнивать)
ax.hist( data_m, bins=30, density=True, color=C_M, alpha=0.6, label="Мужчины" )
ax.hist( data_f, bins=30, density=True, color=C_G, alpha=0.6, label="Женщины" )
статистика
mean_m, std_m = data_m.mean(), data_m.std() mean_f, std_f = data_f.mean(), data_f.std()
линии среднего и std
ax.axvline(mean_m, color=C_M, linewidth=2) ax.axvline(mean_m - std_m, color=C_M, linestyle="--", linewidth=1) ax.axvline(mean_m + std_m, color=C_M, linestyle="--", linewidth=1)
ax.axvline(mean_f, color=C_G, linewidth=2) ax.axvline(mean_f - std_f, color=C_G, linestyle="--", linewidth=1) ax.axvline(mean_f + std_f, color=C_G, linestyle="--", linewidth=1)
подписи
ax.set_title("Распределение роста по полу") ax.set_xlabel("Рост") ax.set_ylabel("Плотность")
ax.legend( frameon=True, facecolor="#FFFDF8", edgecolor="#DDD3C7" )
текстовый блок со статистикой
ax.text( 0.02, 0.95, f"Мужчины: μ = {mean_m:.2f}, σ = {std_m:.2f}\n" f"Женщины: μ = {mean_f:.2f}, σ = {std_f:.2f}", transform=ax.transAxes, ha="left", va="top", fontsize=10, bbox=dict( boxstyle="round,pad=0.35", facecolor="#FFFDF8", edgecolor="#DDD3C7" ) )
plt.tight_layout() plt.show()
График 3
График 3. Распределения роста и веса по полу
Гистограммы демонстрируют форму распределений, а также различия в разбросе значений.
fig, ax = plt.subplots(figsize=(10, 6))
данные
data_m = m[w] data_f = f[w] COL_EDGE = "
1E434C"
тёмный контур / осигистограммы (нормированные)
ax.hist( data_m, bins=30, density=True, color=C_M, alpha=0.6, label="Мужчины" )
ax.hist( data_f, bins=30, density=True, color=C_G, alpha=0.6, label="Женщины" )
статистика
mean_m, std_m = data_m.mean(), data_m.std() mean_f, std_f = data_f.mean(), data_f.std()
линии среднего и стандартного отклонения
ax.axvline(mean_m, color=C_M, linewidth=2) ax.axvline(mean_m - std_m, color=C_M, linestyle="--", linewidth=1) ax.axvline(mean_m + std_m, color=C_M, linestyle="--", linewidth=1)
ax.axvline(mean_f, color=C_G, linewidth=2) ax.axvline(mean_f - std_f, color=C_G, linestyle="--", linewidth=1) ax.axvline(mean_f + std_f, color=C_G, linestyle="--", linewidth=1)
подписи
ax.set_title("Распределение веса по полу") ax.set_xlabel("Вес") ax.set_ylabel("Плотность")
ax.legend( frameon=True, facecolor="#FFFDF8", edgecolor="#DDD3C7" )
текст со статистикой
ax.text( 0.02, 0.95, f"Мужчины: μ = {mean_m:.2f}, σ = {std_m:.2f}\n" f"Женщины: μ = {mean_f:.2f}, σ = {std_f:.2f}", transform=ax.transAxes, ha="left", va="top", fontsize=10, bbox=dict( boxstyle="round,pad=0.35", facecolor="#FFFDF8", edgecolor="#DDD3C7" ) )
plt.tight_layout() plt.show()
График 4
График 4. Средний вес по интервалам роста
Позволяет сравнить средний вес мужчин и женщин при сопоставимом росте и наглядно показать различия между группами.
4-й график: средний вес по интервалам роста (по полу) + std
bins = 12 df2 = df.copy() df2["height_bin"] = pd.cut(df2[h], bins=bins)
stats = (df2.groupby(["height_bin", "gender_norm"])[w] .agg(mean="mean", std="std", n="count") .reset_index())
центры бинов для оси X
stats["x"] = stats["height_bin"].apply(lambda x: (x.left + x.right) / 2)
m_stat = stats[stats["gender_norm"] == "Male"] f_stat = stats[stats["gender_norm"] == "Female"]
fig, ax = plt.subplots(figsize=(10, 6))
ax.errorbar( m_stat["x"], m_stat["mean"], yerr=m_stat["std"], fmt="o-", color=C_M, ecolor=C_M, elinewidth=1, capsize=3, label="Мужчины" )
ax.errorbar( f_stat["x"], f_stat["mean"], yerr=f_stat["std"], fmt="o-", color=C_G, ecolor=C_G, elinewidth=1, capsize=3, label="Женщины" )
ax.set_title("Средний вес по интервалам роста (с разбросом σ)") ax.set_xlabel("Рост (центр интервала)") ax.set_ylabel("Вес (среднее ± σ)") ax.legend(frameon=True, facecolor="
FFFDF8", edgecolor="
DDD3C7")ax.text( 0.02, 0.95, "Идея: сравниваем средний вес при схожем росте.\n" "Вертикальные линии показывают разброс (σ) внутри интервала.", transform=ax.transAxes, ha="left", va="top", fontsize=10, bbox=dict(boxstyle="round,pad=0.35", facecolor="
FFFDF8", edgecolor="
DDD3C7") )plt.tight_layout() plt.show()
Материалы проекта
Jupyter Notebook с кодом анализа:




