Описание проекта
В этом исследовании моей целью было проанализировать данные о пассажирах лайнера Титаник, затонувшего почти 113 лет назад в апреле 1912 года и понять, какими признаками обладали те, кто пережил катастрофу, и по каким признакам можно было бы однозначно предсказать, что у пассажира нет шансов спастись.
Я буду использовать набор данных titanic, являющийся встроенным набором данных в библиотеку визуализации seaborn, которая так же будет использоваться в исследовании для построения графиков.
Визуальное оформление
Было решено подобрать цветовую палитру, которая как-то ассоциировалась бы с этим событием:
базовые цвета — цвета ледяной воды, айсберга и снега BASE_COLORS = [«#F5F5F5», «#B0E0E6», «#003366», «#4B0082», «#C0C0C0»]
золотой и красный — цвета надежды и трагедии SURVIVED_COLORS = [«#FFD700», «#8B0000»]
бордовый и изумрудный были популярными цветами в мужских и женских костюмах начала XX века SEX_COLORS = [«#800020», «#50C878»]
Палитра основных цветов + референс визуального стиля для нейросети
Все изображения были сгенерированы нейросетью Recraft, (все промпты здесь) в качестве стилевого референса было взято изображение Титаника в стиле начала 20 века + наложение цветов палитры.
Начало работы: общие данные
Сначала мне стали интересны общие данные: сколько среди пассажиров было мужчин и женщин, сколько выжило, сколько погибло, сколько путешествовало первым, вторым и третьим классом.
plt.figure(figsize=(10, 6))
Построение сравнительной диаграммы sns.countplot( x='pclass', hue='sex', data=df, palette=SEX_COLORS, hue_order=['male', 'female'] )
Настройка заголовка и подписей plt.title('Количество мужчин и женщин в каждом классе', fontsize=16, fontfamily='serif') plt.xlabel('Класс билета', fontsize=14, fontfamily='serif') plt.ylabel('Количество пассажиров', fontsize=14, fontfamily='serif')
Легенда plt.legend(title='Пол', labels=['Мужчины', 'Женщины'], fontsize=12)
Отображение графика plt.show()
Получается, что большинство пассажиров было мужчинами, и большая часть путешествовала третьим классом.
Теперь исследуем распределение по выжившим и погибшим. Хочется детальнее понять, какой процент пассажиров погиб и выжил относительно класса, которым они путешествовали.
plt.figure(figsize=(10, 6))
sns.countplot( x='pclass', hue='survived', data=df, palette=["#8B0000", "#FFD700"] )
plt.title('Сравнение выживших и погибших пассажиров по классам', fontsize=16, fontfamily='serif') plt.xlabel('Класс', fontsize=14, fontfamily='serif') plt.ylabel('Количество пассажиров', fontsize=14, fontfamily='serif')
plt.legend(title='Выжил', labels=['Погиб', 'Выжил'], fontsize=12)
plt.show()
Пока графики подтверждают очевидный факт: большинство погибших путешествовало третьим классом.
Анализ по гендеру
Теперь проведем следующее исследование: посмотрим статистику по выживаемости мужчин и женщин в каждом классе.
g = sns.catplot( x='pclass', # Ось X: класс пассажира hue='sex', # Разделение по полу col='survived', # Разделение по выживаемости (фасеты) data=df, # Данные kind='count', # Тип графика (гистограмма) palette=SEX_COLORS, # Цветовая палитра height=5, # Высота каждого графика aspect=1.2, # Соотношение сторон hue_order=['male', 'female'], # Порядок отображения пола col_order=[1, 0] # Порядок фасетов: сначала выжившие, затем погибшие )
Настройка заголовков и подписей g.set_titles('{col_name}') # Убираем стандартные заголовки g.set_axis_labels('Класс билета', 'Количество пассажиров') # Подписи осей g.fig.suptitle('Распределение пассажиров по классу, полу и выживаемости', fontsize=16, fontfamily='serif', y=1.05) # Общий заголовок for ax, title in zip(g.axes.flat, ['Выжили', 'Погибли']): ax.set_title(title, fontsize=14, fontfamily='serif')
Легенда g.add_legend(title='Пол') # Добавление легенды
Отображение графика plt.show()
Среди первого и второго класса заметна интересная тенденция: почти нет погибших женщин. Отсюда можно сделать вывод, что состоятельные пассажиры пропускали женщин вперед к шлюпкам.
Анализ по возрасту
Теперь хочется исследовать влияние возраста на шансы спастись. Для этого нужно обработать исходные данные, создав возрастные категории.
def age_category(age): if pd.isnull(age): return 'Unknown' elif age < 12: return 'Child' elif age < 18: return 'Teenager' elif age < 60: return 'Adult' else: return 'Elderly'
Добавление новой колонки с возрастными категориями df['age_category'] = df['age'].apply(age_category)
Уберем тех, чей возраст неизвестен with_age = df.loc[df['age_category'] != 'Unknown', :]
age_counts = with_age['age_category'].value_counts()
plt.figure(figsize=(8, 8)) plt.pie( age_counts, labels=age_counts.index, # Подписи colors=BASE_COLORS, # Цвета autopct='%1.1f%%', # Отображение процентов startangle=90, # Начальный угол shadow=True # Тень )
Заголовок plt.title('Распределение пассажиров по возрастным категориям', fontsize=16, fontfamily='serif')
Отображение диаграммы plt.show()
Создание фасетного графика g = sns.catplot( x='pclass', # Ось X: класс пассажира hue='survived', # Разделение по выживаемости row='age_category', # Разделение по возрастным категориям (фасеты) data=with_age, # Данные kind='count', # Тип графика (гистограмма) palette=SURVIVED_COLORS, # Цветовая палитра height=5, # Высота каждого графика aspect=1.2, # Соотношение сторон row_order=['Child', 'Teenager', 'Adult', 'Elderly'], col_order=[1, 0]# Порядок фасетов )
Настройка заголовков и подписей g.set_titles('Возрастная категория: {row_name}') # Заголовки для фасетов g.set_axis_labels('Класс', 'Количество пассажиров') # Подписи осей g.fig.suptitle('Выживаемость пассажиров по классу и возрастным категориям', fontsize=16, fontfamily='serif', y=1.05) # Общий заголовок
Отображение графика plt.show()
Далее посмотрим на выживаемост:




