import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.metrics import plot_confusion_matrix, classification_report, f1_score
from sklearn.model_selection import train_test_split ,GridSearchCV, cross_val_score
from sklearn.preprocessing import StandardScaler

#Classification Models:
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, VotingClassifier, StackingClassifier
from xgboost import XGBClassifier

#Supress Warnings:
import warnings
warnings.filterwarnings('ignore')
train_df = pd.read_csv('/kaggle/input/titanic/train.csv')
test_df = pd.read_csv('/kaggle/input/titanic/test.csv')
train_df = train_df.set_index("PassengerId")
train_df.head()
train_df.info()
train_df.shape
train_df.isnull().sum()/len(train_df)
train_df.describe()
test_df.isnull().sum()/len(test_df)
train_df.dropna(subset=["Embarked"], inplace=True)
train_df.drop(columns=['Cabin'],inplace=True)

train_df.info()
train_df['Sex'].unique()
train_df['Embarked'].unique()
df_all_corr = train_df.corr().abs().unstack().sort_values(kind="quicksort", ascending=False).reset_index()
df_all_corr.rename(columns={"level_0": "Feature 1", "level_1": "Feature 2", 0: 'Correlation Coefficient'}, inplace=True)
df_all_corr[df_all_corr['Feature 1'] == 'Age']
age_by_pclass_sex = train_df.groupby(['Sex', 'Pclass']).median()['Age']

for pclass in range(1, 4):
    for sex in ['female', 'male']:
        print('Median age of Pclass {} {}s: {}'.format(pclass, sex, age_by_pclass_sex[sex][pclass]))
print('Median age of all passengers: {}'.format(train_df['Age'].median()))

# Filling the missing values in Age with the medians of Sex and Pclass groups
train_df['Age'] = train_df.groupby(['Sex', 'Pclass'])['Age'].apply(lambda x: x.fillna(x.median()))
"""
**DATA Visualization**
"""
plt.figure(figsize=(14,8))
sns.countplot(x="Survived", data=train_df,hue='Sex')
plt.show()
train_df[["Sex", "Survived"]].groupby(['Sex'], as_index=False).mean().sort_values(by='Survived', ascending=False)
plt.figure(figsize=(14,8))
sns.countplot(x="Survived", data=train_df,hue='Pclass')
plt.show()
train_df[['Pclass', 'Survived']].groupby(['Pclass'], as_index=False).mean().sort_values(by='Survived', ascending=False)
plt.figure(figsize=(14,8))
sns.countplot(x="Survived", data=train_df,hue='Embarked')
plt.show()
train_df[["Embarked", "Survived"]].groupby(['Embarked'], as_index=False).mean().sort_values(by='Survived', ascending=False)
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
for dataset in [train_df, test_df]:
    # factorize Name column
    dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
    dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col', 'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
    dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
    dataset['Title'] = dataset['Title'].map(title_mapping)
    dataset['Title'] = dataset['Title'].fillna(0)
    # facotrize Sex column
    dataset['Sex'] = dataset['Sex'].map( {'female': 1, 'male': 0} ).astype(int)
# extract number of family members
for dataset in [train_df, test_df]:
    dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1

train_df[['FamilySize', 'Survived']].groupby(['FamilySize'], as_index=False).mean().sort_values(by='Survived', ascending=False)
for dataset in [train_df, test_df]:
    dataset['IsAlone'] = 0
    dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1

train_df[['IsAlone', 'Survived']].groupby(['IsAlone'], as_index=False).mean()
# factorize values in Embarked column 
freq_port = train_df.Embarked.dropna().mode()[0]
for dataset in [train_df, test_df]:
    dataset['Embarked'] = dataset['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
    
train_df[['Embarked', 'Survived']].groupby(['Embarked'], as_index=False).mean().sort_values(by='Survived', ascending=False)
train_df.columns
features = ['Pclass',  'Sex', 'Age', 'SibSp', 'Parch', 
       'Fare', 'Embarked', 'Title', 'FamilySize', 'IsAlone']
# fill missing values in test df
fare_median = test_df['Fare'].dropna().median()
test_df['Fare'].fillna(fare_median, inplace=True)
test_df['Age'] = test_df.groupby(['Sex', 'Pclass'])['Age'].apply(lambda x: x.fillna(x.median()))
test_df.info()
X = train_df[features]
y = train_df['Survived']

#Split training data into training and validation sets
X_train, X_val, y_train, y_val = train_test_split(X,y,test_size = 0.2,stratify = y,random_state=42)

X_train.info()
# knn - k-nearest neighbours
from sklearn.neighbors import KNeighborsClassifier
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
# print metric to get performance
print("Accuracy: ",model.score(X_val, y_val) * 100)
y_pred = model.predict(X_val)
f1 = f1_score(y_val, y_pred, average='micro')
print("f1_score: ",f1)
print("  Validation set Classification Report:")
print(classification_report(y_val, y_pred, digits=4))
fig, ax = plt.subplots(1, 2, figsize = (15, 5))
ax[0].set_title("Training Set Confusion Matrix")
plot_confusion_matrix(model, X_train, y_train, ax=ax[0], 
                      cmap="YlGnBu", xticks_rotation="vertical")

ax[1].set_title("Validation Set Confusion Matrix")
plot_confusion_matrix(model, X_val, y_val, ax=ax[1],
                      cmap="YlGnBu", xticks_rotation="vertical")
plt.show()
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier

clf = BaggingClassifier(
    DecisionTreeClassifier(), n_estimators=500,
    max_samples=100, bootstrap=True, random_state=42)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_val)
from sklearn.metrics import accuracy_score
print("Accuracy: ",accuracy_score(y_val, y_pred)*100)
f1 = f1_score(y_val, y_pred, average='micro')
print("f1_score: ",f1)
print("  Validation set Classification Report:")
print(classification_report(y_val, y_pred, digits=4))
fig, ax = plt.subplots(1, 2, figsize = (15, 5))
ax[0].set_title("Training Set Confusion Matrix")
plot_confusion_matrix(clf, X_train, y_train, ax=ax[0], 
                      cmap="YlGnBu", xticks_rotation="vertical")

ax[1].set_title("Validation Set Confusion Matrix")
plot_confusion_matrix(clf, X_val, y_val, ax=ax[1],
                      cmap="YlGnBu", xticks_rotation="vertical")
plt.show()
from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(n_estimators=100,
                               criterion="entropy",
                               max_depth=6,
                               min_samples_split=4,
                               bootstrap=True,
                               max_samples=0.8,
                               oob_score=True,
                               n_jobs=-1,
                               random_state=0)

clf.fit(X_train, y_train)
scores=cross_val_score(clf, X, y, cv=5)
print("Cross Validation:\n  %0.5f accuracy with a standard deviation of %0.5f \n" % (scores.mean(), scores.std()))# print metric to get performance
print("Accuracy: ",clf.score(X_val, y_val) * 100)
y_pred = clf.predict(X_val)
f1 = f1_score(y_val, y_pred, average='micro')
print("f1_score: ",f1)
print("  Validation set Classification Report:")
print(classification_report(y_val, y_pred, digits=4))
fig, ax = plt.subplots(1, 2, figsize = (15, 5))
ax[0].set_title("Training Set Confusion Matrix")
plot_confusion_matrix(clf, X_train, y_train, ax=ax[0], 
                      cmap="YlGnBu", xticks_rotation="vertical")

ax[1].set_title("Validation Set Confusion Matrix")
plot_confusion_matrix(clf, X_val, y_val, ax=ax[1],
                      cmap="YlGnBu", xticks_rotation="vertical")
plt.show()
test_df.head()
test_df.info()
predictions = clf.predict(test_df[features])
output = pd.DataFrame({'PassengerId': test_df.PassengerId, 'Survived': predictions})
output.to_csv('my_submission.csv', index=False)
print("Your submission was successfully saved!")