Original size 736x948

Анализ выживаемости пассажиров Титаника с помощью Pandas и визуализаций

PROTECT STATUS: not protected
The project is taking part in the competition

датасет

Название: Titanic passengers Источник: публичный датасет библиотеки seaborn (репозиторий на GitHub) Прямая ссылка: https://raw.githubusercontent.com/mwaskom/seaborn-data/master/titanic.csv

почему эти данные интересны

1.Исторически известная катастрофа, связанная с человеческим фактором. 2.Есть много категориальных и числовых признаков (пол, класс, возраст, стоимость билета и т. д.). 3.Удобно демонстрировать базовые статистические методы и интерпретируемые визуализации.

типы графиков (минимум 4 разных вида)

1. Столбчатая диаграмма (barplot) — общая выживаемость. 2. Составленная (stacked) столбчатая диаграмма — выживаемость по классам. 3. Гистограмма + KDE — распределение возраста по группам выживаемости. 4. Boxplot (ящик с усами) — возраст по полу и классу. 5. Тепловая карта (heatmap) — матрица корреляций числовых признаков.

используемые статистические методы

- Описательная статистика: среднее, медиана, стандартное отклонение (df.describe ()). - Частоты и доли (value_counts, normalize=True) для категориальных признаков. - Группировка и агрегация (groupby + agg, mean как оценка вероятности выживания). - Сводные таблицы (pivot_table). - Корреляция Пирсона для числовых признаков (df.corr ()).

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns

Чтобы графики отображались крупнее и читабельнее

plt.rcParams['figure.figsize'] = (10, 6) plt.rcParams['axes.titlesize'] = 16 plt.rcParams['axes.labelsize'] = 12 plt.rcParams['xtick.labelsize'] = 10 plt.rcParams['ytick.labelsize'] = 10

def set_custom_style ():

Настройка единого стиля инфографики. Здесь создаём минималистичный «журнальный» стиль:  — светлый фон  — приглушённая палитра  — единый шрифт без засечек

sns.set_theme (style="whitegrid») custom_palette = [«

0d6efd», »

20c997», «

fd7e14», »

e83e8c», «#6f42c1»] sns.set_palette (custom_palette) plt.rcParams['font.family'] = 'DejaVu Sans' plt.rcParams['axes.facecolor'] = «#f8f9fa» plt.rcParams['figure.facecolor'] = «#f8f9fa» plt.rcParams['axes.edgecolor'] = «#dee2e6» plt.rcParams['grid.color'] = «#dee2e6»

def load_data ():

Загрузка датасета Titanic из GitHub (seaborn-data). Возвращает DataFrame.

url = «<a rel="noopener" href="https://raw.githubusercontent.com/mwaskom/seaborn-data/master/titanic.csv" data-target="blank" target="_blank">https://raw.githubusercontent.com/mwaskom/seaborn-data/master/titanic.csv"</a>
df = pd.read_csv (url)
return df

def preprocess_data (df):

предобработка данных

- Переименование столбцов для удобства (русские названия в отдельных столбцах)  — Создание новых признаков (family_size, is_child, age_group)  — Обработка пропусков (возраст, класс и т. д. оставляем как есть, но можем фильтровать по необходимости) «»» df = df.copy ()

переименуем некоторые переменные для ясности при визуализации (создадим дубли-столбцы на русском)

df[«Пол»] = df[«sex»].map ({"male»: «Мужчина», «female»: «Женщина"}) df[«Класс»] = df[«class»].map ({"First»: «1 класс», «Second»: «2 класс», «Third»: «3 класс"}) df[«Выжил»] = df[«survived»].map ({0: «Нет», 1: «Да"})

новый признак: размер семьи (чем больше семья, тем потенциально сложнее эвакуация)

df[«family_size»] = df[«sibsp»] + df[«parch»] + 1

новый признак: ребёнок/взрослый (возраст < 16 лет)

df[«is_child»] = np.where (df[«age»] < 16, 1, 0)

группы возраста для более «объясняющего» анализа

bins = [0, 12, 18, 30, 50, 80] labels = [«0-12 (дети)», «13-18 (подростки)», «19-30 (молодые)», «31-50 (взрослые)», «51+ (старшие)»] df[«age_group»] = pd.cut (df[«age»], bins=bins, labels=labels, right=True)

return df

def descriptive_statistics (df):

показ описательной статистики и базовых частот

Это демонстрация использования статистических методов:  — describe () для числовых колонок  — value_counts () и доли (normalize=True) для категорий «»» print («=== Описательная статистика числовых признаков ===») print (df[[«survived», «pclass», «age», «sibsp», «parch», «fare», «family_size»]].describe (), «\n»)

print («=== Распределение по полу ===»)
print (df[«Пол»].value_counts (), «\n»)

print («=== Распределение по полу (доли) ===»)
print (df[«Пол»].value_counts (normalize=True), «\n»)

print («=== Общий уровень выживаемости (доля выживших) ===»)
survival_rate = df[«survived»].mean ()
print (f"Доля выживших: {survival_rate:.2%}\n»)

print («=== Уровень выживаемости по полу ===»)
print (df.groupby («Пол»)[«survived»].mean ().apply (lambda x: f"{x:.2%}»), «\n»)

print («=== Уровень выживаемости по классам ===»)
print (df.groupby («Класс»)[«survived»].mean ().apply (lambda x: f"{x:.2%}»), «\n»)

print («=== Уровень выживаемости по возрастным группам ===»)
print (
    df.groupby («age_group»)[«survived»]
    .mean ()
    .dropna ()
    .apply (lambda x: f"{x:.2%}»)

)

def plot_overall_survival (df):

график 1 (столбчатая диаграмма)

Общий уровень выживаемости на Титанике (количество и доля). Показывает изучающий и объясняющий формат:  — понятные подписи  — подписи процентов на столбиках

Original size 984x579

set_custom_style ()

surv_counts = df[«Выжил»].value_counts ().reindex ([«Да», «Нет»])
surv_rate = df[«survived»].mean ()

fig, ax = plt.subplots ()
sns.barplot (x=surv_counts.index, y=surv_counts.values, ax=ax)

ax.set_title («Выживаемость на Титанике (общее распределение)»)
ax.set_xlabel («Выжил»)
ax.set_ylabel («Количество пассажиров»)

# Подпишем значения на столбиках
for i, v in enumerate (surv_counts.values):
    ax.text (i, v \+ 5, str (v), ha="center», va="bottom», fontweight="bold»)

# Добавим текстовое пояснение с общим процентом выживаемости
ax.text (
    0.5, -0.2,
    f"Общая доля выживших: {surv_rate:.1%}»,
    transform=ax.transAxes,
    ha="center»,
    va="center»,
    fontsize=12

)

plt.tight_layout ()
plt.savefig («plot1_overall_survival.png», dpi=300)
plt.show ()

def plot_survival_by_class_stacked (df):

график 2 (составленная столбчатая диаграмма)

Original size 984x584

Выживаемость по классам (1, 2, 3) — stacked bar. Используется сводная таблица (pivot_table) как статистический метод. «»» set_custom_style ()

pivot = pd.crosstab (df[«Класс»], df[«Выжил»], normalize="index») * 100
pivot = pivot[[«Да», «Нет»]] # порядок столбцов

ax = pivot.plot (
    kind="bar»,
    stacked=True,
    figsize=(10, 6),

)

ax.set_title («Выживаемость по классам (в процентах)»)
ax.set_xlabel («Класс»)
ax.set_ylabel («Доля пассажиров, %»)

# Подпишем проценты внутри столбиков
for c in ax.containers:
    ax.bar_label (c, fmt="%.1f%%», label_type="center»)

plt.legend (title="Выжил»)
plt.tight_layout ()
plt.savefig («plot2_survival_by_class_stacked.png», dpi=300)
plt.show ()

def plot_age_distribution_by_survival (df):

изучающий формат: средний билет и выживаемость по полу и классу

Original size 483x165

Комментарий: - Видно, что пассажиры 1 класса платили больше и имели более высокий шанс выживания. - Женщины в среднем выживали чаще мужчин во всех классах.

график 3 (гистограмма + KDE)

Original size 984x584

Распределение возраста в зависимости от выживания. Используется:  — гистограмма (распределение частот)  — оценка плотности (KDE) как изучающий метод «»» set_custom_style ()

# Фильтруем строки с известным возрастом
age_df = df.dropna (subset=[«age»])

fig, ax = plt.subplots ()
sns.histplot (
    data=age_df,
    x="age»,
    hue="Выжил»,
    element="step»,
    kde=True,
    stat="density»,
    common_norm=False,
    ax=ax,
    bins=25,

)

ax.set_title («Распределение возраста по статусу выживания»)
ax.set_xlabel («Возраст»)
ax.set_ylabel («Плотность»)

plt.tight_layout ()
plt.savefig («plot3_age_distribution_by_survival.png», dpi=300)
plt.show ()

def plot_box_age_by_class_and_sex (df):

график 4 (boxplot)

Original size 984x584

Возраст пассажиров по полу и классу. Позволяет изучить распределение (медиана, квартили, выбросы). «»» set_custom_style ()

age_df = df.dropna (subset=[«age»])

fig, ax = plt.subplots ()
sns.boxplot (
    data=age_df,
    x="Класс»,
    y="age»,
    hue="Пол»,
    ax=ax,

)

ax.set_title («Возраст пассажиров по полу и классу»)
ax.set_xlabel («Класс»)
ax.set_ylabel («Возраст»)

plt.legend (title="Пол»)
plt.tight_layout ()
plt.savefig («plot4_box_age_by_class_and_sex.png», dpi=300)
plt.show ()

def plot_correlation_heatmap (df):

график 5 (тепловая карта корреляций)

Original size 691x584

Матрица корреляций числовых признаков. Используется коэффициент корреляции Пирсона (corr ()). «»» set_custom_style ()

numeric_cols = [«survived», «pclass», «age», «sibsp», «parch», «fare», «family_size», «is_child»]
corr = df[numeric_cols].corr ()

fig, ax = plt.subplots ()
sns.heatmap (
    corr,
    annot=True,
    fmt=».2f»,
    cmap="coolwarm»,
    vmin=-1,
    vmax=1,
    square=True,
    ax=ax,

)

ax.set_title («Корреляция числовых признаков (Пирсон)»)
plt.tight_layout ()
plt.savefig («plot5_correlation_heatmap.png», dpi=300)
plt.show ()

def exploring_and_explaining_examples (df):

примеры «изучающего» и «объясняющего» форматa

  1. Изучающий:  — Посмотрим, как меняется средняя цена билета и шанс выживания в зависимости от класса и пола.

    1. Объясняющий:  — Сформируем табличку с ключевыми метриками по группам.

print («\n=== Изучающий формат: средний билет и выживаемость по полу и классу ===») group_stats = ( df.groupby ([«Пол», «Класс»]) .agg ( mean_fare=(«fare», «mean»), survival_rate=(«survived», «mean»), count=(«survived», «size»), ) .reset_index () )

group_stats[«survival_rate»] = group_stats[«survival_rate»].apply (lambda x: f"{x:.1%}»)
group_stats[«mean_fare»] = group_stats[«mean_fare»].round (2)

print (group_stats.to_string (index=False))

print («\nКомментарий:»)
print (» — Видно, что пассажиры 1 класса платили больше и имели более высокий шанс выживания.»)
print (» — Женщины в среднем выживали чаще мужчин во всех классах.»)

print («\n=== Объясняющий формат: ключевые выводы ===»)
print («1. Общая доля выживших на Титанике около "
      f"{df['survived'].mean ():.1%}.»)
print («2. Наибольшая выживаемость наблюдается у женщин и у пассажиров 1 класса.»)
print («3. Размер семьи и факт, что пассажир ребёнок, также связаны с выживаемостью.»)
print («4. Корреляционная матрица показывает, что класс билета и стоимость билета "
      «связаны между собой и с вероятностью выживания (через социальный статус).»)

def main (): # 1. Загрузка данных df_raw = load_data ()

# 2. Предобработка данных и создание новых признаков
df = preprocess_data (df_raw)

# 3. Описательная статистика и базовый анализ
descriptive_statistics (df)

# 4. Визуализации (минимум 4 разных вида графиков)
plot_overall_survival (df) # График 1: barplot
plot_survival_by_class_stacked (df) # График 2: stacked bar
plot_age_distribution_by_survival (df) # График 3: histogram \+ KDE
plot_box_age_by_class_and_sex (df) # График 4: boxplot
plot_correlation_heatmap (df) # График 5: heatmap

# 5. Примеры изучающего и объясняющего форматов
exploring_and_explaining_examples (df)

print («\nГотово! Графики также сохранены в файлы:»)
print (» — plot1_overall_survival.png»)
print (» — plot2_survival_by_class_stacked.png»)
print (» — plot3_age_distribution_by_survival.png»)
print (» — plot4_box_age_by_class_and_sex.png»)
print (» — plot5_correlation_heatmap.png»)

if name == «main»: main ()

описательная статистика числовых признаков

Original size 895x455
Original size 518x602
Original size 576x170

/tmp/ipython-input-4227034227.py: 125: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning. df.groupby («age_group»)[«survived»]

объясняющий формат: ключевые выводы

1. Общая доля выживших на Титанике около 38,4%. 2. Наибольшая выживаемость наблюдается у женщин и у пассажиров 1 класса. 3. Размер семьи и факт, что пассажир ребёнок, также связаны с выживаемостью. 4. Корреляционная матрица показывает, что класс билета и стоимость билета связаны между собой и с вероятностью выживания (через социальный статус).

В рамках проекта применялась генеративная модель ChatGPT (OpenAI) для помощи в структурировании проекта, формулировке аналитических выводов и оптимизации визуального оформления графиков. ИИ использовался как вспомогательный инструмент и не заменял самостоятельный анализ данных.

We use cookies to improve the operation of the website and to enhance its usability. More detailed information on the use of cookies can be fo...
Show more