%matplotlib inline
import os
import glob
import numpy as np
from scipy import io
import matplotlib.pyplot as plt
import pandas as pd

"""
Explanation: Paris Saclay Center for Data Science
Titanic RAMP: survival prediction of Titanic passengers
Benoit Playe (Institut Curie/Mines ParisTech), Chloé-Agathe Azencott (Institut Curie/Mines ParisTech), Alex Gramfort (LTCI/Télécom ParisTech), Balázs Kégl (LAL/CNRS)
Introduction
This is an initiation project to introduce RAMP and get you to know how it works.
The goal is to develop prediction models able to identify people who survived from the sinking of the Titanic, based on gender, age, and ticketing information. 
The data we will manipulate is from the Titanic kaggle challenge.
Requirements

numpy>=1.10.0  
matplotlib>=1.5.0 
pandas>=0.19.0  
scikit-learn>=0.17 (different syntaxes for v0.17 and v0.18)   
seaborn>=0.7.1
End of explanation
"""


train_filename = 'data/train.csv'
data = pd.read_csv(train_filename)
y_train = data['Survived'].values
X_train = data.drop(['Survived', 'PassengerId'], axis=1)
X_train.head(5)

data.describe()

data.count()

"""
Explanation: Exploratory data analysis
Loading the data
End of explanation
"""


data.groupby('Survived').count()

"""
Explanation: The original training data frame has 891 rows. In the starting kit, we give you a subset of 445 rows. Some passengers have missing information: in particular Age and Cabin info can be missing. The meaning of the columns is explained on the challenge website:
Predicting survival
The goal is to predict whether a passenger has survived from other known attributes. Let us group the data according to the Survived columns:
End of explanation
"""


from pandas.plotting import scatter_matrix
scatter_matrix(data.get(['Fare', 'Pclass', 'Age']), alpha=0.2,
               figsize=(8, 8), diagonal='kde');

"""
Explanation: About two thirds of the passengers perished in the event. A dummy classifier that systematically returns "0" would have an accuracy of 62%, higher than that of a random model.
Some plots
Features densities and co-evolution
A scatterplot matrix allows us to visualize:
* on the diagonal, the density estimation for each feature
* on each of the off-diagonal plots, a scatterplot between two features. Each dot represents an instance.
End of explanation
"""


data_plot = data.get(['Age', 'Survived'])
data_plot = data.assign(LogFare=lambda x : np.log(x.Fare + 10.))
scatter_matrix(data_plot.get(['Age', 'LogFare']), alpha=0.2, figsize=(8, 8), diagonal='kde');

data_plot.plot(kind='scatter', x='Age', y='LogFare', c='Survived', s=50, cmap=plt.cm.Paired);

"""
Explanation: Non-linearly transformed data
The Fare variable has a very heavy tail. We can log-transform it.
End of explanation
"""


import seaborn as sns

sns.set()
sns.set_style("whitegrid")
sns.jointplot(data_plot.Age[data_plot.Survived == 1],
              data_plot.LogFare[data_plot.Survived == 1],
              kind="kde", size=7, space=0, color="b");

sns.jointplot(data_plot.Age[data_plot.Survived == 0],
              data_plot.LogFare[data_plot.Survived == 0],
              kind="kde", size=7, space=0, color="y");

"""
Explanation: Plot the bivariate distributions and marginals of two variables
Another way of visualizing relationships between variables is to plot their bivariate distributions.
End of explanation
"""


from sklearn.compose import make_column_transformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer

categorical_cols = ['Sex', 'Pclass', 'Embarked']
numerical_cols = ['Age', 'SibSp', 'Parch', 'Fare']

preprocessor = make_column_transformer(
    (OneHotEncoder(handle_unknown='ignore'), categorical_cols),
    (SimpleImputer(strategy='constant', fill_value=-1), numerical_cols),
)

"""
Explanation: Making predictions
A basic prediction workflow, using scikit-learn, will be presented below.
First, we will perform some simple preprocessing of our data:

one-hot encode the categorical features: Sex, Pclass, Embarked
for the numerical columns Age, SibSp, Parch, Fare, fill in missing values with a default value (-1)
all remaining columns will be dropped

This can be done succintly with make_column_transformer which performs specific transformations on specific features.
End of explanation
"""


from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression

pipeline = Pipeline([
    ('transformer', preprocessor),
    ('classifier', LogisticRegression()),
])

"""
Explanation: The preprocessor object created with make_column_transformer can be used in a scikit-learn pipeline. A pipeline assembles several steps together and can be used to cross validate an entire workflow. Generally, transformation steps are combined with a final estimator.
We will create a pipeline consisting of the preprocessor created above and a final estimator, LogisticRegression.
End of explanation
"""


from sklearn.model_selection import cross_val_score

scores = cross_val_score(pipeline, X_train, y_train, cv=8, scoring='roc_auc')

print("mean: %e (+/- %e)" % (scores.mean(), scores.std()))

"""
Explanation: We can cross-validate our pipeline using cross_val_score. Below we will have specified cv=8 meaning KFold cross-valdiation splitting will be used, with 8 folds. The Area Under the Receiver Operating Characteristic Curve (ROC AUC) score is calculated for each split. The output score will be an array of 8 scores from each KFold. The score mean and standard of the 8 scores is printed at the end.
End of explanation
"""


test_filename = 'data/test.csv'
data = pd.read_csv(test_filename)
y_test = data['Survived'].values
X_test = data.drop(['Survived', 'PassengerId'], axis=1)
X_test.head(5)

"""
Explanation: Testing
Once you have created a model with cross-valdiation scores you are happy with, you can test how well your model performs on the independent test data.
First we will read in our test data:
End of explanation
"""


clf = pipeline.fit(X_train, y_train)

"""
Explanation: Next we need to fit our pipeline on our training data:
End of explanation
"""


y_pred = pipeline.predict(X_test)

"""
Explanation: Now we can predict on our test data:
End of explanation
"""


from sklearn.metrics import roc_auc_score

score = roc_auc_score(y_test, y_pred)
score

"""
Explanation: Finally, we can calculate how well our model performed on the test data:
End of explanation
"""


from sklearn.compose import make_column_transformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression

def get_estimator():

    categorical_cols = ['Sex', 'Pclass', 'Embarked']
    numerical_cols = ['Age', 'SibSp', 'Parch', 'Fare']

    preprocessor = make_column_transformer(
        (OneHotEncoder(handle_unknown='ignore'), categorical_cols),
        (SimpleImputer(strategy='constant', fill_value=-1), numerical_cols),
    )

    pipeline = Pipeline([
        ('transformer', preprocessor),
        ('classifier', LogisticRegression()),
    ])

    return pipeline

"""
Explanation: RAMP submissions
For submitting to the RAMP site, you will need to write a submission.py file that defines a get_estimator function that returns a scikit-learn pipeline.
For example, to submit our basic example above, we would define our pipeline within the function and return the pipeline at the end. Remember to include all the necessary imports at the beginning of the file.
End of explanation
"""


# !ramp_test_submission

"""
Explanation: If you take a look at the sample submission in the directory submissions/starting_kit, you will find a file named submission.py, which has the above code in it.
You can test that the sample submission works by running ramp_test_submission in your terminal (ensure that ramp-workflow has been installed and you are in the titanic ramp kit directory). Alternatively, within this notebook you can run:
End of explanation
"""


