Введение в анализ данных¶
Титаник¶
Был крупнейшим пассажирским судном в 1912—1913 годах. Во время первого рейса затонул в северной Атлантике, столкнувшись с айсбергом в ночь с 14 на 15 апреля 1912 года, при этом погибло 1502 из 2224 пассажиров и членов экипажа.
Данные о пассажирах были собраны в таблицы, которые можно скачать с Kaggle. Эти данные часто используются в качестве обучающих в анализе данных.
Этот обучающий ноутбук на примерах показывает основную функциональность библиотек pandas
и seaborn
.
Подробные обучающие ноутбуки можно посмотреть по ссылкам:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(palette='Set2', font_scale=1.3)
1. Чтение данных¶
Подробнее про чтение и запись данных.
Прочитаем данные с помощью библиотеки pandas
. Библиотека pandas предназначена для статистической обработки данных, по функциональности близкий к SQL и R. Включает в себя функциональность работы с базами данных и таблицами Excel.
При чтении укажем, что первую колонку нужно использовать в качестве индекса (т.е. ключа) в таблице: index_col=0
.
Мы видим таблицу со следующими колонками:
Pclass
— класс пассажира (1
— высший,2
— средний,3
— низший);Name
— имя;Sex
— пол;Age
— возраст;SibSp
— количество братьев, сестер, сводных братьев, сводных сестер, супругов на борту титаника;Parch
— количество родителей, детей (в том числе приемных) на борту титаника;Ticket
— номер билета;Fare
— плата за проезд;Cabin
— каюта;Embarked
— порт посадки (C
— Шербур;Q
— Квинстаун;S
— Саутгемптон).
data = pd.read_csv('train.csv', index_col=0)
data
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
PassengerId | |||||||||||
1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
887 | 0 | 2 | Montvila, Rev. Juozas | male | 27.0 | 0 | 0 | 211536 | 13.0000 | NaN | S |
888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 19.0 | 0 | 0 | 112053 | 30.0000 | B42 | S |
889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | 0 | 0 | 111369 | 30.0000 | C148 | C |
891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 11 columns
Можно вывести только строго указанное количество строк.
data.head(2)
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
PassengerId | |||||||||||
1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
Соответствующая переменная имеет тип данных DataFrame
.
type(data)
pandas.core.frame.DataFrame
2. Способы извлечения данных¶
Данные из отдельной колонки.
data['Name']
PassengerId 1 Braund, Mr. Owen Harris 2 Cumings, Mrs. John Bradley (Florence Briggs Th... 3 Heikkinen, Miss. Laina 4 Futrelle, Mrs. Jacques Heath (Lily May Peel) 5 Allen, Mr. William Henry ... 887 Montvila, Rev. Juozas 888 Graham, Miss. Margaret Edith 889 Johnston, Miss. Catherine Helen "Carrie" 890 Behr, Mr. Karl Howell 891 Dooley, Mr. Patrick Name: Name, Length: 891, dtype: object
Если имя колонки "достаточно хорошее", то можно и так.
data.Name
PassengerId 1 Braund, Mr. Owen Harris 2 Cumings, Mrs. John Bradley (Florence Briggs Th... 3 Heikkinen, Miss. Laina 4 Futrelle, Mrs. Jacques Heath (Lily May Peel) 5 Allen, Mr. William Henry ... 887 Montvila, Rev. Juozas 888 Graham, Miss. Margaret Edith 889 Johnston, Miss. Catherine Helen "Carrie" 890 Behr, Mr. Karl Howell 891 Dooley, Mr. Patrick Name: Name, Length: 891, dtype: object
Данные по столбцу имеют тип данных Series
.
type(data.Name)
pandas.core.series.Series
Можно вытащить сразу несколько колонок.
data[['Survived', 'Pclass', 'Name']]
Survived | Pclass | Name | |
---|---|---|---|
PassengerId | |||
1 | 0 | 3 | Braund, Mr. Owen Harris |
2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... |
3 | 1 | 3 | Heikkinen, Miss. Laina |
4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) |
5 | 0 | 3 | Allen, Mr. William Henry |
... | ... | ... | ... |
887 | 0 | 2 | Montvila, Rev. Juozas |
888 | 1 | 1 | Graham, Miss. Margaret Edith |
889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" |
890 | 1 | 1 | Behr, Mr. Karl Howell |
891 | 0 | 3 | Dooley, Mr. Patrick |
891 rows × 3 columns
Имена всех колонок.
data.columns
Index(['Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'], dtype='object')
Список всех индексов таблицы (т.е. ключей).
data.index
Int64Index([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... 882, 883, 884, 885, 886, 887, 888, 889, 890, 891], dtype='int64', name='PassengerId', length=891)
Название колонки-индекса.
data.index.name
Тип данных в каждой из колонок таблицы.
data.dtypes
Survived int64 Pclass int64 Name object Sex object Age float64 SibSp int64 Parch int64 Ticket object Fare float64 Cabin object Embarked object dtype: object
Строку таблицы, соответствующую ключу 1, можно получить через loc
.
data.loc[1]
Survived 0 Pclass 3 Name Braund, Mr. Owen Harris Sex male Age 22 SibSp 1 Parch 0 Ticket A/5 21171 Fare 7.25 Cabin NaN Embarked S Name: 1, dtype: object
Обратите внимание, что обычный численный индекс этой строки равен 0. По нему также можно извлекать строку с помощью iloc
.
data.iloc[0]
Survived 0 Pclass 3 Name Braund, Mr. Owen Harris Sex male Age 22 SibSp 1 Parch 0 Ticket A/5 21171 Fare 7.25 Cabin NaN Embarked S Name: 1, dtype: object
Если же попробовать запустить:
то возникнет исключение KeyError: 0
, поскольку ключа 0
в этой таблице нет.
Можно извлечь несколько строк:
data.iloc[0:3]
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
PassengerId | |||||||||||
1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
Можно извлечь конкретное значение:
data.iloc[0]['Name']
'Braund, Mr. Owen Harris'
data.iloc[0, 2]
data.describe()
Survived | Pclass | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 714.000000 | 891.000000 | 891.000000 | 891.000000 |
mean | 0.383838 | 2.308642 | 29.699118 | 0.523008 | 0.381594 | 32.204208 |
std | 0.486592 | 0.836071 | 14.526497 | 1.102743 | 0.806057 | 49.693429 |
min | 0.000000 | 1.000000 | 0.420000 | 0.000000 | 0.000000 | 0.000000 |
25% | 0.000000 | 2.000000 | 20.125000 | 0.000000 | 0.000000 | 7.910400 |
50% | 0.000000 | 3.000000 | 28.000000 | 0.000000 | 0.000000 | 14.454200 |
75% | 1.000000 | 3.000000 | 38.000000 | 1.000000 | 0.000000 | 31.000000 |
max | 1.000000 | 3.000000 | 80.000000 | 8.000000 | 6.000000 | 512.329200 |
Идентификация пропусков в таблице.
data.isna()
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
PassengerId | |||||||||||
1 | False | False | False | False | False | False | False | False | False | True | False |
2 | False | False | False | False | False | False | False | False | False | False | False |
3 | False | False | False | False | False | False | False | False | False | True | False |
4 | False | False | False | False | False | False | False | False | False | False | False |
5 | False | False | False | False | False | False | False | False | False | True | False |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
887 | False | False | False | False | False | False | False | False | False | True | False |
888 | False | False | False | False | False | False | False | False | False | False | False |
889 | False | False | False | False | True | False | False | False | False | True | False |
890 | False | False | False | False | False | False | False | False | False | False | False |
891 | False | False | False | False | False | False | False | False | False | True | False |
891 rows × 11 columns
Можно посчитать долю пропущенных значений в каждой колонке.
data.isna().mean()
Survived 0.000000 Pclass 0.000000 Name 0.000000 Sex 0.000000 Age 0.198653 SibSp 0.000000 Parch 0.000000 Ticket 0.000000 Fare 0.000000 Cabin 0.771044 Embarked 0.002245 dtype: float64
Сортировка по столбцу.
data.sort_values(by='Age')
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
PassengerId | |||||||||||
804 | 1 | 3 | Thomas, Master. Assad Alexander | male | 0.42 | 0 | 1 | 2625 | 8.5167 | NaN | C |
756 | 1 | 2 | Hamalainen, Master. Viljo | male | 0.67 | 1 | 1 | 250649 | 14.5000 | NaN | S |
645 | 1 | 3 | Baclini, Miss. Eugenie | female | 0.75 | 2 | 1 | 2666 | 19.2583 | NaN | C |
470 | 1 | 3 | Baclini, Miss. Helene Barbara | female | 0.75 | 2 | 1 | 2666 | 19.2583 | NaN | C |
79 | 1 | 2 | Caldwell, Master. Alden Gates | male | 0.83 | 0 | 2 | 248738 | 29.0000 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
860 | 0 | 3 | Razi, Mr. Raihed | male | NaN | 0 | 0 | 2629 | 7.2292 | NaN | C |
864 | 0 | 3 | Sage, Miss. Dorothy Edith "Dolly" | female | NaN | 8 | 2 | CA. 2343 | 69.5500 | NaN | S |
869 | 0 | 3 | van Melkebeke, Mr. Philemon | male | NaN | 0 | 0 | 345777 | 9.5000 | NaN | S |
879 | 0 | 3 | Laleff, Mr. Kristo | male | NaN | 0 | 0 | 349217 | 7.8958 | NaN | S |
889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
891 rows × 11 columns
3.2 Графики с помощью seaborn
¶
Посмотрим, как можно работать с библиотекой seaborn
. Это популярная библиотека готовых шаблонов для статистической визуализации, написанная на бэкенде matplotlib
. Она имеет высокоуровневый интерфейс и по умолчанию может строить более эстетичные графики.
Построим гистограмму по возрасту отдельно для мужчин и женщин.
with sns.axes_style('whitegrid'):
plt.figure(figsize=(9, 5))
sns.histplot(data=data, x='Age', hue='Sex')
Построим боксплоты (ящики с усами) для стоимости билета в зависимости от класса.
with sns.axes_style('whitegrid'):
plt.figure(figsize=(9, 4))
sns.boxplot(data=data, x='Fare', y='Pclass', orient='h')
Ограничим значения по горизонтальной оси.
with sns.axes_style('whitegrid'):
plt.figure(figsize=(9, 4))
sns.boxplot(data=data, x='Fare', y='Pclass', orient='h')
plt.xlim((-5, 170))
3.3 Более сложные операции из pandas
¶
Подробнее про группировку данных.
Сгруппируем данные по классу и усредним по всем численным колонкам.
data.groupby(by='Pclass').mean()
Survived | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|
Pclass | |||||
1 | 0.629630 | 38.233441 | 0.416667 | 0.356481 | 84.154687 |
2 | 0.472826 | 29.877630 | 0.402174 | 0.380435 | 20.662183 |
3 | 0.242363 | 25.140620 | 0.615071 | 0.393075 | 13.675550 |
Похожим образом можно для каждого класса посчитать функции минимума и максимума.
data.groupby(by='Pclass').aggregate([min, max])
Survived | Name | Sex | Age | SibSp | Parch | Ticket | Fare | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
min | max | min | max | min | max | min | max | min | max | min | max | min | max | min | max | |
Pclass | ||||||||||||||||
1 | 0 | 1 | Allen, Miss. Elisabeth Walton | Young, Miss. Marie Grice | female | male | 0.92 | 80.0 | 0 | 3 | 0 | 4 | 110152 | WE/P 5735 | 0.0 | 512.3292 |
2 | 0 | 1 | Abelson, Mr. Samuel | del Carlo, Mr. Sebastiano | female | male | 0.67 | 70.0 | 0 | 3 | 0 | 3 | 11668 | W/C 14208 | 0.0 | 73.5000 |
3 | 0 | 1 | Abbing, Mr. Anthony | van Melkebeke, Mr. Philemon | female | male | 0.42 | 74.0 | 0 | 8 | 0 | 6 | 12460 | W./C. 6609 | 0.0 | 69.5500 |
Подробнее про агрегирующие функции.
С помощью функции crosstab
можно очень легко получить информацию о том, сколько человек определенного пола ехали в таком-то классе, а также сумму по строкам и столбцам.
pd.crosstab(data['Sex'], data['Pclass'], margins=True)
Pclass | 1 | 2 | 3 | All |
---|---|---|---|---|
Sex | ||||
female | 94 | 76 | 144 | 314 |
male | 122 | 108 | 347 | 577 |
All | 216 | 184 | 491 | 891 |
А с помощью похожей функции pivot_table
можно легко получить информацию о том, каков максимальный возраст среди пассажиров определенного пола для каждого класса.
pd.pivot_table(
data,
values='Age',
index='Sex',
columns='Pclass',
aggfunc=np.max
)
Pclass | 1 | 2 | 3 |
---|---|---|---|
Sex | |||
female | 63.0 | 57.0 | 63.0 |
male | 80.0 | 70.0 | 74.0 |
Почитайте также про операции объединения таблиц, например, merge
и join
.