<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Alumnos
Step1:  Importamos los datos para entrenar y testear
Step2:  Miramos los datos, para ver que si hay nulos o datos que rellenar, como la edad y la cabina en este caso
Step3:  Faltan muchos datos de edad y cabina por rellenar, ademas de 2 embarcos
Miramos los tipos de los datos
Step4:  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
Step5:  Analisis a primera vista de los datos
Hay que rellenar los datos que faltan para poder usarlo en los algoritmos de entrenamiento
Hay que pasar todos los strings a valores numericos para poder usarlo en los algoritmos de entrenamiento
Hay que descartar features que sean inutiles o crear nuevas features a partir de las nuevas para entrenar
Visualizacion grafica de la relacion entre las features
Step6:  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
Step7:  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
Step8:  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
Step9:  Rellenar la edad
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
Step10:  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
Step11:  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
Step12:  Clasificamos el nombre segun el titulo de una persona
Step13:  Quitamos los titulos especiales y los agrupamos en categorias mas concretas
Step14:  Eleccion del Modelo
Hemos probado con 4 modelos diferentes a ver cual da mejor resultado, y en este caso, Random Forest ha sido el daba mas puntuacion en kaggle, de entre los 3 que empataban a score (RF, DT y SVM)
Step15:  Random Forest
Step16:  Decision Tree
Step17:  Support Vector Machines
Step18:  KNN
Step19:  Creamos el archivo submission para subir a kaggle
Step20:  Lo guardamos en formato csv
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import pandas as pd
import numpy as np
import random as rnd
import seaborn as sns
import matplotlib.pyplot as plt
Explanation: Alumnos: Cristhian Rodriguez y Jesus Perucha
Practica 3:  Titanic
End of explanation
train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')
Explanation: Importamos los datos para entrenar y testear
End of explanation
print(train_df.columns.values)
train_df.isnull().sum()
Explanation: Miramos los datos, para ver que si hay nulos o datos que rellenar, como la edad y la cabina en este caso
End of explanation
print (train_df.info())
train_df.describe()
Explanation: Faltan muchos datos de edad y cabina por rellenar, ademas de 2 embarcos
Miramos los tipos de los datos
End of explanation
train_df, test_df = train_df.drop(['Cabin', 'Ticket'], axis=1), test_df.drop(['Cabin', 'Ticket'], axis=1)
# Sacamos la descripcion de los valores que son Strings (object)
train_df.describe(include=['O'])
Explanation: 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
End of explanation
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
# 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)
# 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')
sns.countplot(x = 'Survived', hue='Embarked', data=train_df)
# Tambien hay una ligera correlacion con el lugar de embarque
Explanation: Analisis a primera vista de los datos
Hay que rellenar los datos que faltan para poder usarlo en los algoritmos de entrenamiento
Hay que pasar todos los strings a valores numericos para poder usarlo en los algoritmos de entrenamiento
Hay que descartar features que sean inutiles o crear nuevas features a partir de las nuevas para entrenar
Visualizacion grafica de la relacion entre las features
End of explanation
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)
#Rellenamos el unico valor que falta de fare
test_df['Fare'] = test_df['Fare'].fillna(test_df['Fare'].median())
# 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)
Explanation: 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
End of explanation
for df in [train_df, test_df]:
    df['FamilySize'] = df['Parch'] + df['SibSp'] + 1
sns.barplot(x='FamilySize', y='Survived' , data=train_df)
Explanation: 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
End of explanation
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)
train_df = train_df.drop(['Parch', 'SibSp'], axis=1)
test_df = test_df.drop(['Parch', 'SibSp'], axis=1)
Explanation: 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
End of explanation
corrmat = train_df.corr()
sns.heatmap(corrmat, square=True)
print ("El numero de datos Age sin rellenar: ",train_df['Age'].isnull().sum())
plt.title('Distribucion de la edad original', size=20, y=1.1)
sns.distplot(train_df['Age'].dropna())
#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())
Explanation: Rellenar la edad
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
End of explanation
plt.title('Distribucion de la edad rellena', size=20, y=1.1)
sns.distplot(train_df['Age'])
#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)
Explanation: 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
End of explanation
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()
train_df = train_df.drop(['AgeBand'], axis=1)
Explanation: 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
End of explanation
# 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)
    
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)
    
Explanation: Clasificamos el nombre segun el titulo de una persona
End of explanation
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)
# Borramos la columna Name
train_df = train_df.drop(['Name', 'PassengerId'], axis=1)
test_df = test_df.drop(['Name'], axis=1)
train_df.head()
Explanation: Quitamos los titulos especiales y los agrupamos en categorias mas concretas
End of explanation
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
Explanation: Eleccion del Modelo
Hemos probado con 4 modelos diferentes a ver cual da mejor resultado, y en este caso, Random Forest ha sido el daba mas puntuacion en kaggle, de entre los 3 que empataban a score (RF, DT y SVM)
End of explanation
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
Explanation: Random Forest
End of explanation
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)
Explanation: Decision Tree
End of explanation
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)
Explanation: Support Vector Machines
End of explanation
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)
Explanation: KNN
End of explanation
submission = pd.DataFrame({
        "PassengerId": test_df["PassengerId"],
        "Survived": Y_pred
    })
Explanation: Creamos el archivo submission para subir a kaggle
End of explanation
submission.to_csv('submission.csv', index=False)
Explanation: Lo guardamos en formato csv
End of explanation
<END_TASK>