In [48]:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
import numpy as np
import math as m
from scipy.stats import boxcox
from scipy.stats import shapiro
%matplotlib inline
In [2]:
train = pd.read_csv('train.csv')
train.head()
Out[2]:
In [3]:
train.shape
Out[3]:
In [4]:
test = pd.read_csv('test.csv')
test.head()
Out[4]:
In [5]:
test.shape
Out[5]:
В ходе решения Titanic_2.0 мы получили baseline- 0.76077, проведем глубокое исследование данных и попытаемся улучшить эти значения
Только 2 непрерывных признака, остальные дискретные. Возмодно можно будет понастраивать кодирование признаков
In [14]:
train.info()
In [15]:
test.info()
В обоих выборках много пропусков занчений признака "Age", практически отсутствуют значения признака "Cabin", пропущено одно значение прзнака Fare в тестовой выборке
In [5]:
train.Survived.describe()
Out[5]:
In [6]:
plt.title(u'Количесто погибших/выжевших на титанике', y= 1.1, size=15)
sns.countplot(x='Survived', data = train)
Out[6]:
Классы получились не сбалансированными, учесть это при обучении моделей
In [9]:
train.Pclass.describe()
Out[9]:
In [22]:
plt.title(u'Распределение выживших в зависимости от класса', y= 1.1, size = 20 )
sns.barplot(x = 'Pclass', y = 'Survived', data = train)
Out[22]:
сильный признак
In [24]:
plt.title(u'Количество людей путешествубщих в каждоим классе', y= 1.1, size=15)
sns.countplot(x='Pclass', data = train)
Out[24]:
In [27]:
sex_encoder = LabelEncoder()
train['Sex_enc'] = sex_encoder.fit_transform(train.Sex)
test['Sex_enc'] = sex_encoder.transform(test.Sex)
In [29]:
plt.title(u'Число мужчин и женщин на борту', y =1.1, size = 20)
sns.countplot(x='Sex', data = train)
Out[29]:
In [30]:
plt.title(u'Распределение выживших в зависимости от класса и пола', y= 1.1, size = 20 )
sns.barplot(x = 'Pclass', y = 'Survived', data = train, hue = 'Sex')
Out[30]:
Класс и пол - очень сильные признаки
In [39]:
sns.countplot(x='SibSp', data = train)
Out[39]:
In [44]:
sns.countplot(x='Parch', data = train)
Out[44]:
создадим признак Family Size, чтобы добавить вес правому краю распредления
In [4]:
for df in [train,test]:
df['Fam_size'] = df.Parch + df.SibSp
In [5]:
sns.countplot(x='Fam_size', data = train)
Out[5]:
In [48]:
fig = plt.figure(figsize = (10,10))
sns.barplot(x='Fam_size', y = 'Survived', hue = 'Sex',data = train)
Out[48]:
In [49]:
fig = plt.figure(figsize = (10,10))
sns.barplot(x='Fam_size', y = 'Survived', hue = 'Pclass',data = train)
Out[49]:
Очень сильный признак. Бездетные люди из 3 класса практически не имели шансов выжить
In [6]:
train.Ticket.describe()
Out[6]:
In [7]:
for elem in df.Ticket:
print elem
#print elem[0]
Первая буква билета может означать серию или еще какую-то информаци о продавце билетов, что возможно могло повлиять на групировку пассажиров на борту
In [8]:
train['letter'] = df.Ticket.apply(lambda x: x[0])
In [9]:
fig = plt.figure(figsize = (10,10))
plt.title(u'Распределение пасажиров по классам в завимимость от первой буквы номер билета', size = 20)
sns.countplot(x='letter',hue='Pclass', data = train)
Out[9]:
In [10]:
fig = plt.figure(figsize = (10,10))
sns.barplot(x='letter',y = 'Survived', hue='Pclass', data = train)
Out[10]:
Признак слабоват
Некоторые номера билетов повторяются, разделим их на повторяющиеся и нет
In [26]:
ticket = pd.concat((train.Ticket, test.Ticket), ignore_index = True)
ticket_freq = ticket.value_counts()
for df in (train,test):
fticket_list = []
for elem in df.Ticket:
if ticket_freq[str(elem)]>1:
fticket_list.append(1)
else:
fticket_list.append(0)
df['ticket_freq'] = fticket_list
In [31]:
plt.title(u'Доля выживших в зависимости от пола и наличия у человека повторяющегося билета', size = 20)
sns.barplot(x = 'ticket_freq', y = 'Survived', data = train, hue = 'Sex')
Out[31]:
In [32]:
plt.title(u'Доля выживших в зависимости от пола и наличия у человека повторяющегося билета', size = 20)
sns.barplot(x = 'ticket_freq', y = 'Survived', data = train, hue = 'Pclass')
Out[32]:
Признак средней силы, так как перекрываются доверительные интервалы
In [7]:
fig = plt.figure(figsize=(10,10))
plt.title(u'Распределение стоимости билета в обучающей выборке', y= 1.1, size = 20 )
sns.distplot(train.Fare)
Out[7]:
In [14]:
fig = plt.figure(figsize=(10,10))
plt.title(u'Распределение стоимости билета в тестовой выборке', y= 1.1, size = 20 )
sns.distplot(test.Fare.loc[test.Fare.isnull() == False])
Out[14]:
На обучении и на тесте распределение признака Fare явно не является нормальным. Объеденим значения и попытаемся привести их к нормальному распределению
В ходе исследования признака оказальсь что есть пасажиры, которые не платили за билет, исследуем их
In [14]:
train.Fare.loc[train.Fare == 0]
Out[14]:
In [16]:
train.Survived.loc[train.Fare == 0]
Out[16]:
In [15]:
sns.barplot(x =train.Fare.loc[train.Fare == 0] , y = 'Survived', data = train, hue = 'Pclass')
Out[15]:
In [17]:
sns.barplot(x =train.Fare.loc[train.Fare == 0] , y = 'Survived', data = train, hue = 'Sex')
Out[17]:
Пасажиры с бесплатными билетами - мужчины из 3-его класса с практически нулевым шансом на выживание. Созжадим признак free_ticket, 1- бесплтный билет, 0 - платный билет
In [20]:
for df in (train, test):
df['free_ticket'] = df.Fare.apply(lambda x: 1 if x==0 else 0)
In [41]:
# заменим значения 0 на 0,01 так как дальнейшие преобразования с 0 будут плохо работать
for df in (train, test):
df.Fare = df.Fare.apply(lambda x:0.01 if x==0 else x)
In [42]:
train['log_fare'] = train.Fare.apply(np.log10)
In [43]:
sns.distplot(train.log_fare)
Out[43]:
In [47]:
sns.distplot(boxcox(train.Fare)[0])
Out[47]:
In [49]:
shapiro(boxcox(train.Fare)[0])
Out[49]:
In [ ]:
train.Fare.loc[train.Fare <= 0]
In [37]:
plt.title(u'Распределение людей по возрасту', y= 1.1, size = 20 )
sns.distplot(train.Age.loc[train.Age.isnull()== False])
Out[37]:
In [38]:
train.Age.loc[train.Age.isnull()== False].describe()
Out[38]: