Alumnos: Cristhian Rodriguez y Jesus Perucha
In [1]:
%matplotlib inline
import pandas as pd
import numpy as np
import random as rnd
import seaborn as sns
import matplotlib.pyplot as plt
In [2]:
train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')
In [3]:
print(train_df.columns.values)
train_df.isnull().sum()
Out[3]:
Faltan muchos datos de edad y cabina por rellenar, ademas de 2 embarcos
In [4]:
print (train_df.info())
train_df.describe()
Out[4]:
Como faltan mas de la mitad de los datos de la cabina y no contienen informacion util, se puede descartar esta feature.
Tambien vamos a quitar ticket, porque no hay relacion ninguna entre los nombres de los tickets
In [5]:
train_df, test_df = train_df.drop(['Cabin', 'Ticket'], axis=1), test_df.drop(['Cabin', 'Ticket'], axis=1)
In [6]:
# Sacamos la descripcion de los valores que son Strings (object)
train_df.describe(include=['O'])
Out[6]:
In [7]:
plt.title('Survival count between sex', size=20, y=1.1)
sns.countplot(x = 'Survived', hue='Sex', data=train_df)
#Hay una gran correlacion entre el sexo y la supervivencia
Out[7]:
In [8]:
# Pasamos el sexo de string a un int, 1 para hombre y 0 para mujer
for df in [train_df, test_df]:
df['Sex'] = df['Sex'].apply(lambda x : 1 if x == 'male' else 0)
In [9]:
# Hay relacion directa entre la clase y la supervivencia
plt.figure(figsize=(12, 12))
plt.subplot(2,2,1)
plt.title('Survival rate / Pclass', size=15, y=1.1)
sns.barplot(x='Pclass', y = 'Survived', data=train_df, palette='muted')
Out[9]:
In [10]:
sns.countplot(x = 'Survived', hue='Embarked', data=train_df)
# Tambien hay una ligera correlacion con el lugar de embarque
Out[10]:
Como faltan 2 datos de embarque de 2 personas y usaremos la feature, rellenamos con S porque es donde la mayoria de las personas lo han hecho y hay menos riesgo de falsear las features. Tambien pasamos de S,C,Q a valores enteros para entrenarlos
In [11]:
train_df['Embarked'] = train_df['Embarked'].fillna('S')
for dt in [train_df, test_df]:
dt['Embarked'] = dt['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
In [12]:
#Rellenamos el unico valor que falta de fare
test_df['Fare'] = test_df['Fare'].fillna(test_df['Fare'].median())
In [13]:
# Transformamos los valores continuos de fare en valores discretos, agrupando los rangos en 4 grupos, del 0 al 3
for df in [train_df, test_df]:
df['Fare'] = pd.qcut(df['Fare'], 4, labels=[0, 1, 2, 3])
train_df.head(5)
Out[13]:
Como Parch es la abreviacion de 'parent/children', sumado y SibSp es la abreviacion de 'sibling/spouse' sumados, se pueden juntar estas 2 features en una sola que representen el tamaño de la familia que tiene esa persona, incluyendola. Sacamos la grafica para ver la relacion que hay
In [14]:
for df in [train_df, test_df]:
df['FamilySize'] = df['Parch'] + df['SibSp'] + 1
In [15]:
sns.barplot(x='FamilySize', y='Survived' , data=train_df)
Out[15]:
De esta grafica podemos ver que las personas con 2,3 o 4 de tamaño familiar, tenian mas posibilidades de supervivencia Asi que vamos a simplicar esta nueva feature en 0 si esta fuera de 2,3 o 4 miembros en el barco y 1 si lo esta. Con esto las features Parch y SibSp no hacen falta
In [16]:
def filter_family_size(x):
if x == 1:
return 0
elif x < 5:
return 1
else:
return 0
for df in [train_df, test_df]:
df['FamilySize'] = df['FamilySize'].apply(filter_family_size)
In [16]:
In [17]:
train_df = train_df.drop(['Parch', 'SibSp'], axis=1)
test_df = test_df.drop(['Parch', 'SibSp'], axis=1)
La forma mas precisa de hacerlo es usando la mediana y la correlaciones que la edad tiene con otras features,en este caso las mas correladas son el genero y pclass, como se ve en el diagrama de calor de abajo.
A partir de la edad he creado una nueva feature con el rango de edades, para ver la supervivencia entre rangos
In [18]:
corrmat = train_df.corr()
sns.heatmap(corrmat, square=True)
print ("El numero de datos Age sin rellenar: ",train_df['Age'].isnull().sum())
In [19]:
plt.title('Distribucion de la edad original', size=20, y=1.1)
sns.distplot(train_df['Age'].dropna())
Out[19]:
In [20]:
#Rellenamos los campos edad vacios
guess_ages = np.zeros((2,3))
for dataset in [train_df, test_df]:
for i in range(0, 2):
for j in range(0, 3):
guess_df = dataset[(dataset['Sex'] == i) & \
(dataset['Pclass'] == j+1)]['Age'].dropna()
# age_mean = guess_df.mean()
# age_std = guess_df.std()
# age_guess = rnd.uniform(age_mean - age_std, age_mean + age_std)
age_guess = guess_df.median()
# Convert random age float to nearest .5 age
guess_ages[i,j] = int( age_guess/0.5 + 0.5 ) * 0.5
for i in range(0, 2):
for j in range(0, 3):
dataset.loc[ (dataset.Age.isnull()) & (dataset.Sex == i) & (dataset.Pclass == j+1),\
'Age'] = guess_ages[i,j]
dataset['Age'] = dataset['Age'].astype(int)
print ("El numero de datos Age sin rellenar: ",train_df['Age'].isnull().sum())
Al haber introducido los nuevos datos sobre la media, la distribucion sigue siendo igual a antes de introducirlos, pero con un repunte de datos en la zona de la mediana
In [21]:
plt.title('Distribucion de la edad rellena', size=20, y=1.1)
sns.distplot(train_df['Age'])
Out[21]:
In [22]:
#Creamos la nueva feature y la mostramos
train_df['AgeBand'] = pd.cut(train_df['Age'], 8)
train_df[['AgeBand', 'Survived']].groupby(['AgeBand'], as_index=False).mean().sort_values(by='AgeBand', ascending=True)
sns.countplot(x='Survived', hue='AgeBand' , data=train_df)
Out[22]:
Convertimos el campo edad en valores de 0 al 7 siguiendo la feature banda de edades que hemos creado antes, con este cambio, banda de edades es una feature que no necesitamos ya
In [23]:
for dataset in [train_df, test_df]:
dataset.loc[ dataset['Age'] <= 10, 'Age'] = 0
dataset.loc[(dataset['Age'] > 10) & (dataset['Age'] <= 20), 'Age'] = 1
dataset.loc[(dataset['Age'] > 20) & (dataset['Age'] <= 30), 'Age'] = 2
dataset.loc[(dataset['Age'] > 30) & (dataset['Age'] <= 40), 'Age'] = 3
dataset.loc[(dataset['Age'] > 40) & (dataset['Age'] <= 50), 'Age'] = 4
dataset.loc[(dataset['Age'] > 50) & (dataset['Age'] <= 60), 'Age'] = 5
dataset.loc[(dataset['Age'] > 60) & (dataset['Age'] <= 70), 'Age'] = 6
dataset.loc[ dataset['Age'] > 70, 'Age'] = 7
train_df.head()
Out[23]:
In [25]:
train_df = train_df.drop(['AgeBand'], axis=1)
In [24]:
# Filter the name
def get_title(x):
y = x[x.find(',')+1:].replace('.', '').replace(',', '').strip().split(' ')
if y[0] == 'the': # Search for the countess
title = y[1]
else:
title = y[0]
return title
def filter_title(title, sex):
if title in ['Countess', 'Dona', 'Lady', 'Jonkheer', 'Mme', 'Mlle', 'Ms', 'Capt', 'Col', 'Don', 'Sir', 'Major', 'Rev', 'Dr']:
if sex:
return 'Rare_male'
else:
return 'Rare_female'
else:
return title
for df in [train_df, test_df]:
df['NameLength'] = df['Name'].apply(lambda x : len(x))
df['Title'] = df['Name'].apply(get_title)
In [26]:
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
for dataset in [train_df, test_df]:
dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)
In [27]:
#Quitamos los titulos especiales y los agrupamos en categorias mas concretas
for df in [train_df, test_df]:
df['Title'] = df.apply(lambda x: filter_title(x['Title'], x['Sex']), axis=1)
sns.countplot(y=train_df['Title'])
train_df.groupby('Title')['PassengerId'].count().sort_values(ascending=False)
Out[27]:
In [28]:
# Borramos la columna Name
train_df = train_df.drop(['Name', 'PassengerId'], axis=1)
test_df = test_df.drop(['Name'], axis=1)
In [29]:
train_df.head()
Out[29]:
In [30]:
X_train = train_df.drop(["Survived"], axis=1).copy()
Y_train = train_df["Survived"]
X_test = test_df.drop("PassengerId", axis=1).copy()
X_train.shape, Y_train.shape, X_test.shape
Out[30]:
In [ ]:
X_test.head()
In [ ]:
X_train.head()
In [31]:
from sklearn.ensemble import RandomForestClassifier
random_forest = RandomForestClassifier(n_estimators=101)
random_forest.fit(X_train, Y_train)
Y_pred = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
#acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
#acc_random_forest
Out[31]:
In [37]:
from sklearn import tree
clf = tree.DecisionTreeClassifier()
clf.fit(X_train, Y_train)
Y_pred = clf.predict(X_test)
clf.score(X_train, Y_train)
Out[37]:
In [35]:
from sklearn.svm import SVC
svc = SVC(C=10000.0)
svc.fit(X_train, Y_train)
Y_pred = svc.predict(X_test)
svc.score(X_train, Y_train)
Out[35]:
In [34]:
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, Y_train)
Y_pred = knn.predict(X_test)
knn.score(X_train, Y_train)
Out[34]:
In [38]:
submission = pd.DataFrame({
"PassengerId": test_df["PassengerId"],
"Survived": Y_pred
})
In [39]:
submission.to_csv('submission.csv', index=False)