import matplotlib.pyplot as plt
import seaborn as sns
import warnings

warnings.filterwarnings('ignore')
sns.set()
# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All" 
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
"""
# 0) Let's explore our data
"""
data = pd.read_csv('/kaggle/input/titanic/train.csv')
data.head(3)
data.shape
"""
## Feature description 
|Feature|Description|Value|
|---|---|---|
|survival|Survival |0 = No, 1 = Yes
|pclass|Ticket class|1 = 1st, 2 = 2nd, 3 = 3rd
|sex||
|Age|Age in year|
|sibsp|	# of siblings / spouses aboard the Titanic	|
|parch|	# of parents / children aboard the Titanic	|
|ticket|	Ticket number	|
|fare	Passenger fare	|
|cabin	|Cabin number	|
|embarked	|Port of Embarkation|	C = Cherbourg, Q = Queenstown, S = Southampton
"""
"""
## Declare the color for each target
"""
survived = sns.color_palette()[2]   # Green
died = sns.color_palette()[3]       # Red
data_vis = data.copy()
data_vis['Survived'] = data_vis['Survived'].replace({0:'Died', 1:'Survived'})
"""
## 0.1) Looking into 'passenger class'
"""
sns.countplot(data=data_vis, x='Pclass', hue='Survived', palette={'Died':died, 'Survived':survived})
plt.xticks([0,1,2],['Upper class','Middle class','Lower class'])
plt.xlabel('Passenger Class')
plt.title('Survivors/Deaths in each passenger class')
plt.show()
"""
We can obviously see that passengers in 'Upper class' are more likely to survive than other classes, While the 'Lower class' passengers are died the most.
"""
"""
## 0.2) Looking into 'Age'
"""
#sns.histplot(data=data_vis, x='Age', hue='Survived', multiple='layer', element='step', palette={'Died':died, 'Survived':survived}, hue_order=['Survived','Died'])

plt.hist(data_vis[data_vis['Survived']=='Died']['Age'], histtype='stepfilled', color=died, alpha=0.6, label='Died', bins=np.linspace(0,80,20))
plt.hist(data_vis[data_vis['Survived']=='Survived']['Age'], histtype='stepfilled', color=survived, alpha=0.6, label='Survived', bins=np.linspace(0,80,20))
plt.title('Survivors/Deaths\' distribution')
plt.xlabel('Age')
plt.ylabel('Count')
plt.legend(title='Survived')
plt.show()
"""
From histogram above, we see that most passengers are 20-50 years old. <br>
Also, we notice that child passenger(0-20 years old) has more survived than died.  
"""
"""
## 0.3) Looking into 'gender'
"""
sns.countplot(data=data_vis, x='Sex', hue='Survived', palette={'Died':died, 'Survived':survived})
plt.title('Survivors/Deaths\' gender')
plt.xlabel('Gender')
plt.show()
"""
There are a very obvious trend here. Male is much more likely to die than female. <br>

"""
"""
### My guess by looking to the data, <br>
'Upper class', 'Children', 'Female' passenger are more likely to survie.
"""
"""
## 0.4) Looking into 'embarked town'
"""
sns.countplot(data=data_vis, x='Embarked', hue='Survived', palette={'Died':died, 'Survived':survived})
plt.xticks([0,1,2],['Southampton', 'Cherbourg',  'Queenstown'])
plt.title('Survivors/Deaths classified by embarked town')
plt.xlabel('Embarked town')
plt.show()
"""
# 1) Preprocessing
"""
"""
## 1.1) Feature Selection
"""
"""
### Drop identity: 'PassengerID', 'Name', 'Ticket'
"""
data.drop(['PassengerId', 'Name', 'Ticket'], axis=1, inplace=True)
data.head(3)
"""
## 1.2) Missing value
"""
missing = pd.DataFrame(data.isnull().sum()/len(data), columns=['NaN'])

missing.style.background_gradient(cmap=sns.light_palette("red", as_cmap=True))
"""
We see that 'Cabin' is 77.1% missing. Thus, we manage to drop this feature.
"""
data = data.drop(['Cabin'], axis=1)
"""
'Age' will be imputed with its mean.
"""
from sklearn.impute import SimpleImputer

imputer = SimpleImputer(missing_values=np.nan, strategy='mean').fit(data[['Age']])

data_imputed = data.copy()
data_imputed[['Age']] = imputer.transform(data_imputed[['Age']])

"""
'Embarked' will be forwward filled.
"""
data_imputed.fillna(method='ffill', inplace=True)
data_imputed.isnull().sum()
"""
## 1.3) Encoding categorical features**
"""
data_imputed.head(3)
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer

X, y = data_imputed.drop('Survived',axis=1), data_imputed[['Survived']]


ohe = OneHotEncoder().fit(X.loc[:,['Sex','Embarked']])

ct = ColumnTransformer([
    ('One Hot Encode', ohe, [1,6])
], remainder='passthrough')


data_imputed_encoded = ct.fit_transform(X)
"""
## 1.4) Scale the data
"""
X_train, X_test, y_train, y_test = train_test_split(data_imputed_encoded, y, test_size=0.2, stratify=y)
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler().fit(X_train)

X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
"""
# 2) Building the learning models
"""
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import confusion_matrix, classification_report, plot_roc_curve, roc_auc_score

models = dict()

models['Logistic Regression'] = LogisticRegression()
models['Decision Tree'] = DecisionTreeClassifier()
models['Random Forest'] = RandomForestClassifier(criterion='gini',
                                           n_estimators=1750,
                                           max_depth=7,
                                           min_samples_split=6,
                                           min_samples_leaf=6,
                                           max_features='auto',
                                           oob_score=True,
                                           n_jobs=-1,) 
models['Gradient Boosting'] = GradientBoostingClassifier()
models['Support Vector'] = SVC()
models['Naive Bayes'] = GaussianNB()


def fit_models(models, X_train_scaled, y_train):
    for x in models:
        models[x].fit(X_train_scaled, y_train)
        print(x+': fitted')

def get_report(models, X_test_scaled, y_test):
    reports = dict()
    for x in models:
        model = models[x]
        y_pred = model.predict(X_test_scaled)
        reports[x] = [confusion_matrix(y_test, y_pred),classification_report(y_test, y_pred), roc_auc_score(y_test, y_pred)]
        print(x+': reported')
    return reports

fit_models(models, X_train_scaled, y_train)
reports = get_report(models, X_test_scaled, y_test)
for each in reports:
    cm, cr, roc = reports[each]
    print('------------'+each+'------------')
    print(roc)
    print(cm)
    print(cr)
def PREPROCESS(data):
    
    # 1.1) Feature Selection: drop identity
    data.drop(['PassengerId', 'Name', 'Ticket'], axis=1, inplace=True)
    
    # 1.2) Missing Value
        # Drop too many missing
    data.drop(['Cabin'], axis=1, inplace=True)
        # Impute numerical feaure
    data_imputed = data.copy()
    data_imputed[['Age']] = imputer.transform(data_imputed[['Age']])
        # Forward fill categorical features
    data_imputed.fillna(method='ffill', inplace=True)
    
    # 1.3) Encode categorical features
    data_imputed_encoded = ct.fit_transform(data_imputed)
    
    # 1.4) Scale the data
    X_test_scaled = scaler.transform(data_imputed_encoded)
    
    return X_test_scaled
    
TEST = pd.read_csv('/kaggle/input/titanic/test.csv')
index = TEST['PassengerId']
TEST.head(3)
TEST_PREPROCESS = PREPROCESS(TEST)
test_pred = models['Support Vector'].predict(TEST_PREPROCESS)

out = pd.DataFrame({'Survived':test_pred}, index=index)
out.to_csv('OUTPUT_2.csv')