# 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 plotly.express as px
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.metrics import accuracy_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import GridSearchCV




# 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


titan = pd.read_csv("/kaggle/input/titanic/train.csv")
titan.head()




test = pd.read_csv("/kaggle/input/titanic/test.csv")
test.head()


"""
#  <span style="color:Green">EXPLORE THE DATA </span>
"""
titan.describe()
titan.select_dtypes('object').describe()
titan.info()
"""
There is missing data in
   - Age
   - Cabin
   - Embarked
   
There is quite alot of missing data from Age and Cabin.
"""
titan.groupby(['Survived'])['PassengerId'].count()
titan.groupby(['Survived'])['PassengerId'].count()/titan['Survived'].count()
"""
Base survival rate is 0.3838
"""
"""
## PLOT OUT 'SURVIVAL VS DEMISE' ON SELECTED FEATURES 

"""
# Select features to examine the survival rate 
cols = ['Pclass', 'Age', 'SibSp', 'Parch', 'Sex','Cabin','Embarked']

for col in cols:
    table = titan.pivot_table(columns = 'Survived', index = col, values = 'PassengerId', aggfunc = 'count')
    fig = px.bar(table, barmode = 'group')
    fig.show()
"""
## OBSERVATIONS ON PLOTS
1. Pclass
    - class 3 has the most passengers 
    - among the 3 class , it has the most passenger who perished
    - class 3 death rate is nearly 3 times as high compare to the other classes 
    - class 1 clearly has the best odds of survival 
    
2. Age
    - from the chart it seems young children have better survival rates
    - the elderly seem to have a lower chance of survival
    - no clear pattern as to how age might contribute to survivor rate 
    - there are quite alot of missing data as well . 177 empty cells
    
3. SibSp and Parch
    - out of 342 survivors . 210 travelled alone which is like 61% of survivors
    - its seems that travel alone or with just 1 or 2 family members seems to improve odds of survival.
4. Sex
    - gender plays quite a distinct role in determining if a passenger will survival
    - it will be interesting to examine the data to find among the women who die and men who survived if there is any particular attribute that improves their survival
5. Cabin
    - could not see any clear trend from the plots
    - cabin have a lot of missing data
    - examination with excel: looking at cabin with other features , could find any relation it has with other features.
    - other than most class 1 passengers have their cabins recorded
6. Embarked
    - majority of passengers boarded from S
    - majority of passengers from S did not survived as well. Many class 3 passengers are also from S
    - C passengers looks to have the highest chance of survival 
    
"""
"""
## EXAMINE REMAING FEATURES:  1.'NAME' | 2.'TICKETS | 3. 'FARE'

## 1.Name
- will be looking at each individual titles to separate into different groups
- based on feature examination 'Sex' . Found that women are more likely to survived . 
- However among women are singles and married, who is more likely to survive ?
- Examine Miss and Mrs
- Master is a title for young male that are still not of age . Will that have any impact for death rate among males ?
- Break down the types of titles and examine further
"""
title =[ i.split(',')[1].split('.')[0].strip() for i in titan.Name ]
titan['title'] =[ i.split(',')[1].split('.')[0].strip() for i in titan.loc[:,'Name']]
titan.head()
Surbytitle = titan.pivot_table(index = 'Survived', columns = 'title' , values = 'PassengerId', aggfunc = 'count')
Surbytitle
Titlesurvival_rate = Surbytitle.iloc[1].fillna(0)/Surbytitle.sum()
Titlesurvival_rate.sort_values( ascending=False)

"""
From the table
- Mrs holds the highest survival rate follow by Miss and Master 
- Mrs are definitely adults 
- Miss and Master consist of children and young adults
- Will look at adding Mr, Mrs,Miss and Master to features
- Rev seems to have all perished. Might add Rev as feature as well 
- Might add Dr as well
"""
"""
## 2.Tickets

 Wiki info:
- according to wiki there are deck A to deck G .
- lower decks are mostly occupied by 3 class passengers
- likelyhood that the top deck passengers are more likely to survive
- perhaps the numbering or alphabets of the ticket could have reference to which deck and which part of it, the passenger is located
- breaking the tickets into letters and numbers might help in finding trends.

"""
ticket_letter = [i.lower().split(' ')[0].replace('/','').replace('.','') if i.isnumeric()==False else i.replace(i,'Numeric') for i in titan.Ticket]
ticket_numeric = [i if i.isnumeric() else i.split(' ')[-1] for i in titan.Ticket]
titan['ticket_letter'] = ticket_letter
titan['ticket_numeric'] = ticket_numeric
titan.head()
"""
### 2.1 TICKET_LETTER
"""
titan.groupby(['ticket_letter','Survived']).PassengerId.count()
"""
- Some ticket_letters like wc, a4, a5 show clear leaning to one side in survivor rates
"""
"""
### 2.2 TICKET_NUMERIC

The ticket numbers are unique to each passenger or their group of travellers(family).

Examination of the ticket_numerics show:
- there are different number of digits (3, 4, 5, 6, 7)
- tickets that the same number of digit and that share similar numbers in the first 2 or 3 digits belong to the same class or might be embarked from the same location
"""
# create 3 digit class feature for all numeric tickets (1st digit be len of the number of digits ) (next 2 digit slice of the first 2 numbers ) ex: 17655 will be 517.
titan.loc[ titan.ticket_letter == 'Numeric','ticket_letter'] = titan.ticket_numeric.str.len().astype(str) + titan.ticket_numeric.str.slice(0,2).astype(str)

pd.options.display.max_rows = 100
titan.groupby(['ticket_letter','Survived'])['PassengerId'].count().head(100)
"""
### 2.3 FARE
"""
for i in range(1,4):
    print('class:',i)
    print(titan[titan['Pclass']==i]['Fare'].describe())
#pd.options.display.max_rows = 200
for i in range(1,4):
    fig = px.scatter(titan.pivot_table(columns = 'Survived',index = titan[titan['Pclass']==i]['Fare'], values = 'PassengerId',aggfunc = 'count'),title = 'Pclass'+str(i))
    fig.show()
"""
For class 1 and 2 , it looks like there are more red dots with high values (Survivors) beyond the mean fare
"""
"""
# <span style="color:Green">EXAMINE FEATURES : BUILD PROFILES</span>


**'Pclass', 'Name', 'Sex', 'Age', 'SibSp','Parch','Embarked','Fare' features can be use to build passenger profiles which determine their base odds of survival.**

**So PCLASS, SEX and EMBARKED plots shows very clear relation to survival rates.** 
1. Can combine the 3 features to create distinct passenger profiles
    - Example : Female Class 1 Passenger from C 
    - Example : Male Class 2 Passenger from S
    - 2 Sex , 3 Pclass, 3 Embark , total of 18 passenger profile tpyes
    
2. Name contains titles:
    - Mr, Mrs, Miss, Master, Rev , Dr . 6 titles to be created as features
    - other titles have too few samples are to be grouped into Mr or Mrs
    
AGE wise young children tend to have higher survival rates and the elderly seem to have a lower chance of survival.    

3. Create a new feature to distinct between children (0-14)  , adults and elderly (50 -80)


SibSp and Parch will help determine they are travelling alone or with families.                

4. Create features to segregate those travelling alone and those with children


Fare wise , there seems to be more survivors among those passengers who paid higher than the mean fare for class 1 and 2.

5. Can create a feature to differentiate passengers who paid a higher fare than usual for class 1 and class 2



**'Ticket',  'Cabin' are environment attributes which will increase or decrease a passenger rate of survival.**

From exploration of the data, i find cabin feature does not contribute much to determine survival or death rates and there are too many missing data.
Tickets seems to be more useful. 
1. Create features from the letters of each tickets and from the numeric ones create a 3 digit class feature. From them select feartures that have good amount of samples or display strong disposition towards a result. 
               



"""
"""
# <span style="color:Green">FEATURE ENGINEERING</span>
"""
"""
## Combine Test and Titan dataset for feature creation across the 2 datasets
"""
# revert back original
titan = pd.read_csv("/kaggle/input/titanic/train.csv")
titan['Dataset'] = 0
test['Dataset'] = 1   # 1 is data from the test set
titan_all = pd.concat([titan,test])

titan_all_copy = titan_all.copy()
titan_all_copy=titan_all_copy.reset_index()
titan_all_copy.head()
titan_all_copy.tail()
"""
##  Feature Creation
1. - From Names derive titles feature:
    1. Mr
    2. Mrs
    3. Master
    4. Miss
    5. Rev
    6. Dr
    - Retain the above 6 titles as features . The rest will be group into Mr or Mrs or Miss accordingly
    
    
2. - Create Maturity feature:
    1. adults are age 14 and above
    2. children are age 13 and below
    3. Elder are age 50 and above
    - For NaN , if Parch = 0 set as adult or Title = Mr or Mrs.
    - if title = Master or Miss set as child


3. - From Maturity Info segregate into male or female Adults who are travelling with children.
    1. male with Child
    2. female with Child
    3. travel with No Child


4. - Pclass break down passengers in each class into male , female and child.
    1. class1 male
    2. class1 female
    3. class1 child

5. - Create ticket_letter and ticket_numeric
    1. ticket letters 
    2. and create new categories from ticket_numeric
    3. Replace numeric tickets in ticket_letter with new categories from ticket_numeric
    
6. - Embarked
    1. NaN cells in Embarked to be replace with the most passengers embarked location
    2. Embark to be combine with Pclass to form passenger profiles
        - 3 class types , 3 embark locations , 2 sex gender and child.
        - Potentially : Total of 27 passenger profile types .
   
 
   
7. - from Parch and SibSip create new feature Gender-Companion
    1. To have male and female passenger who travelled alone or with companions
     
     
- Remove : 
    1. Sex
    2. Names
    3. PassengerId
    4. Ticket
    5. Fare
    6. cabin
    7. Ticket_Numeric
     
     
     
#### 'Embarked', 'title', 'ticket_letter', 'Maturity', 'Gender-Companions', 'TravelwithChild' will be first use for exploration

"""
"""
## Feature Engineering 1) titles
"""
titan_all_copy['title'] =[ i.split(',')[1].split('.')[0].strip() for i in titan_all_copy.loc[:,'Name']]
titan_all_copy.head()
"""
#### 1.1) Convert unwanted titles to others
"""
titan_all_copy['title'].value_counts()
"""
Convert female titles to Mrs
1. MIle
2. the Countess
3. Mme
4. Lady
5. Dona

Convert female titles to Miss
1. Ms

Convert male titles to Mr
1. Col
2. Major
3. Capt
4. Don
5. Sir
6. Jonkheer
"""
titlelist = ['Mr','Mrs','Master','Miss','Rev','Dr']
Mrslist = ['Mlle','the Countess','Mme','Lady','Dona']
Mslist = ['Ms']
Mrlist = ['Col','Major','Capt','Don','Sir','Jonkheer']

titan_all_copy.loc[titan_all_copy['title'].isin(Mrslist),'title'] = 'Mrs'
titan_all_copy.loc[titan_all_copy['title'].isin(Mrlist),'title'] = 'Mr'
titan_all_copy.loc[titan_all_copy['title'].isin(Mslist),'title'] = 'Miss'
titan_all_copy.tail()
"""
## Feature Engineering 2) Maturity 
"""
titan_all_copy[titan_all_copy.title == 'Master'].Age.max()
titan_all_copy[titan_all_copy.title == 'Mr'].Age.min()
"""
I will use the average of age 13 and below to determine if a passenger is a child 
"""
def Maturity(x):
    for i in range(len(x['Age'])):
        if pd.isna(x['Age'][i]):
            if x['Parch'][i] == 0 or x['title'][i] in ['Mr','Mrs']:
                x.loc[i,'Maturity']= 'Adult'
            elif x['title'][i] == 'Master':
                x.loc[i,'Maturity']= 'Child'    
            else:
                x.loc[i,'Maturity']= 'Child'
        if x.loc[i,'Age'] >= 14:
            x.loc[i,'Maturity']= 'Adult'
        if x['Age'][i]<14:
            x.loc[i,'Maturity']='Child'
        if x.loc[i,'Age'] >= 50:
            x.loc[i,'Maturity']= 'Elderly'

Maturity(titan_all_copy)
titan_all_copy.head(10)
"""
## Feature Engineering 3) From Maturity Info segregate into Male or Female Adults who are travelling with children
"""
# Family name to find group of travellers who are in the same family 
titan_all_copy['fname']=titan_all_copy.Name.str.split(',',expand= True)[0]
titan_all_copy['fname']

# find all the children with their respective family names and ticket no. 
fchild = titan_all_copy.loc[titan_all_copy.Maturity == 'Child',['fname','Ticket']]
fchild.head()
def travelwithchild(x):
    for i in range(len(x.fname)):
        for j,g in fchild.values:
            if x.fname[i] == j and x.Ticket[i] == g and (x.Maturity[i] == 'Adult' or x.Maturity[i] == 'Elderly'):
                x.loc[i,'TravelwChild'] =  x.Sex[i] +'withChild'
                break
            else:
                x.loc[i,'TravelwChild'] = 'NotwithChild'
travelwithchild(titan_all_copy)

#(titan_all_copy['TravelwChild'] !=  'NotwithChild').sum()
((titan_all_copy.TravelwChild == 'femalewithChild') | ( titan_all_copy.TravelwChild == 'malewithChild')).sum()

titan_all_copy[(titan_all_copy['TravelwChild'] == 'femalewithChild')|(titan_all_copy['TravelwChild'] == 'malewithChild')].head()
"""
## Feature Engineering 4) Turn Pclass into categorical data
"""
titan_all_copy.Pclass = titan_all_copy.Pclass.astype(str)
titan_all_copy.dtypes
# breaking down passengers in each class into male , female and child.
titan_all_copy['Pclass'] = [titan_all_copy.Pclass[i]+titan_all_copy.Sex[i] if titan_all_copy.Maturity[i] != 'Child' else titan_all_copy.Pclass[i]+ 'Child' for i in range(len(titan_all_copy.Pclass))]
titan_all_copy.head(10)
"""
## Feature Engineering 5) Turn tickets into Features
"""
# creat ticket_letter
ticket_letter = [i.lower().split(' ')[0].replace('/','').replace('.','') if i.isnumeric()==False else i.replace(i,'Numeric') for i in titan_all_copy.Ticket]
# create ticket_numeric
ticket_numeric = [i if i.isnumeric() else i.split(' ')[-1] for i in titan_all_copy.Ticket]
titan_all_copy['ticket_letter'] = ticket_letter
titan_all_copy['ticket_numeric'] = ticket_numeric
titan_all_copy.head()
titan_all_copy.ticket_letter.describe()
# create 3 digit feature for all numeric tickets (1st digit len ) (next 2 digit slice)
titan_all_copy.loc[ titan_all_copy.ticket_letter == 'Numeric','ticket_letter'] = titan_all_copy.ticket_numeric.str.len().astype(str) + titan_all_copy.ticket_numeric.str.slice(0,2).astype(str)

#keep all that has more than 20 samples
pd.options.display.max_rows = 200
titan_all_copy.ticket_letter.value_counts().head(50)
#SELECT THOSE WITH HAVE HIGH SURVIVED OR DEATH RATES
titan_all_copy.groupby(['ticket_letter','Survived']).Survived.count()
#Option 1 : Select those with more than 20 samples and above or those with clear leanings towards a result
#ticklist = ['634','611','pc','426','441','475','a4','638','ca','623','636','624','635','637','a5','633','631','stono','511','sotonoq','519','528','513','731']

#Option 2:  Deleted some with 20 or less samples and  those with big samples but do not show strong relationship with survival.
ticklist = ['634','611','pc','426','ca','623','636','624','635','637','a5','633','631','stono','511','sotonoq','519','528','513']

titan_all_copy.loc[~titan_all_copy.ticket_letter.isin(ticklist),'ticket_letter'] = 'Others'
titan_all_copy.head()
"""
## Feature Engineering 6) Embarked : Passenger Profiles

"""
titan_all_copy['Embarked'].mode()
"""
Most passengers are from S. From replace NaN 'Embarked' cells with S
"""
r = titan_all_copy['Embarked'].isna()
titan_all_copy.loc[r,'Embarked']='S'
titan_all_copy['Embarked'].isna().sum()# should turn up NO rows as NaN are converted to S
# Combine Embarked with Plcass to form Passenger Profiles
titan_all_copy['Embarked'] = titan_all_copy.Embarked + titan_all_copy.Pclass
titan_all_copy.head(10)
"""
## Feature Engineering 7) Combine Sex with Parch and SibSip to  Create Gender-Companions Feature

#### GenderComp Feature : Females that are single and Females with companions as well Males that are single or with companions
- FS for single females   
    - Sex= female and Parch and SibSp = 0


- FC for females with ompanions 
    - Sex - female and ( Parch >0 or SibSp >0)


- MS for single males            
    - Sex= female and Parch and SibSp = 0 
    
    
- MC for males with companions
    - Sex - male and ( Parch >0 or SibSp >0)
    

"""
def GenderComp(x):
    for i in range(len(x.Sex)):
        if x.Sex[i] == 'female' and x.Parch[i] == 0 and x.SibSp[i] == 0:
            x.loc[i,'GenderComp'] = 'FS'
        elif x.Sex[i] == 'female' and (x.Parch[i] > 0 or x.SibSp[i] > 0):
            x.loc[i,'GenderComp'] = 'FC'
        elif x.Sex[i] == 'male' and x.Parch[i] == 0 and x.SibSp[i] == 0:
            x.loc[i,'GenderComp'] = 'MS'
        elif x.Sex[i] == 'male' and (x.Parch[i] > 0 or x.SibSp[i] > 0):
            x.loc[i,'GenderComp'] = 'MC'
"""
#### To test out creating categories : gender travelling with different group
Option 2:

def GenderComp(x):
    for i in range(len(x.Sex)):
        if x.Sex[i] == 'female' and x.Parch[i] + x.SibSp[i] == 0:
            x.loc[i,'GenderComp'] = 'FS0'
            
        elif x.Sex[i] == 'female' and (0 < x.Parch[i] + x.SibSp[i] < 3):
            x.loc[i,'GenderComp'] = 'FC1-2'
            
        elif x.Sex[i] == 'female' and  2 < x.Parch[i] + x.SibSp[i] < 5:
            x.loc[i,'GenderComp'] = 'FC3-4'
            
        elif x.Sex[i] == 'female' and  4 < x.Parch[i] + x.SibSp[i] < 7:
            x.loc[i,'GenderComp'] = 'FC5-6'
            
        elif x.Sex[i] == 'female' and  x.Parch[i] + x.SibSp[i] > 6:
            x.loc[i,'GenderComp'] = 'FC>6'      
            
        elif x.Sex[i] == 'male' and x.Parch[i] == 0 and x.SibSp[i] == 0:
            x.loc[i,'GenderComp'] = 'MS0'
            
        elif x.Sex[i] == 'male' and (x.Parch[i] + x.SibSp[i] >= 1) and (x.Parch[i] + x.SibSp[i] < 3):
            x.loc[i,'GenderComp'] = 'MC1-2'
            
        elif x.Sex[i] == 'male' and  2 < x.Parch[i] + x.SibSp[i] < 5:
            x.loc[i,'GenderComp'] = 'MC3-4'
        
        elif x.Sex[i] == 'male' and  4 < x.Parch[i] + x.SibSp[i] < 7:
            x.loc[i,'GenderComp'] = 'MC5-6'
            
        elif x.Sex[i] == 'male' and  x.Parch[i] + x.SibSp[i] > 6:
            x.loc[i,'GenderComp'] = 'MC>6'  
"""
GenderComp(titan_all_copy)
titan_all_copy.head()
titan_all_copy.info()
"""
# <span style="color:Green">PREPARING DATA FOR MODELING </span>

"""
"""
## Using Dummies to create features
"""
#dummies = pd.get_dummies(titan_all_copy[['Pclass','Embarked','title','ticket_letter','Maturity','GenderComp']])
dummies = pd.get_dummies(titan_all_copy[['Embarked','title','ticket_letter','Maturity','GenderComp','TravelwChild']])
dummies
print('No. of features:',len(dummies.columns))
dummies.columns  
dummies.drop('TravelwChild_NotwithChild', axis = 1, inplace = True)
print('No. of features:',len(dummies.columns))
"""
### SPLIT DUMMIES INTO TRAIN_X , TEST_X
"""
dummies['dataset'] = titan_all_copy.Dataset
train_X = dummies[dummies.dataset == 0]
train_X.drop("dataset", axis = 1, inplace = True)
train_X
train_Y = titan.Survived
test_X = dummies[dummies.dataset == 1]
test_X.drop("dataset", axis = 1,inplace = True)
test_X
"""
# <span style="color:Green">START MODELING </span>
"""
"""
## MODELLING WITH SVM
"""
# Base Score
model = svm.SVC()
model.fit(train_X,train_Y)
predictionsSVM = model.predict(train_X)
acc = accuracy_score(train_Y,predictionsSVM)
acc
# RBF
C = [0.1, 0.2, 0.3, 0.5,0.6,0.7,0.8,0.9, 1, 1.5, 2, 3,4,5,6,7,8,9,10,20,50,100]
gamma = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.5, 2, 3,4,5,6,7,8,9,10,20,50,100]
best = 0
for i in C:
    for j in gamma:
        model = svm.SVC(C= i, kernel = 'rbf', gamma = j)
        model.fit(train_X,train_Y)
        predictionsSVM = model.predict(train_X)
        acc = accuracy_score(train_Y,predictionsSVM)
        if acc > best:
            best = acc
            print('best score so far:',acc , '  Kernel:rbf ', 'C:',i,' gamma:',j)
# Poly (Best results so far)
C = [ 0.1, 0.2, 0.3, 0.5, 1, 2, 3,4,5,6,7,8,9,10,20,50,100]
degree = [0,1, 2, 3,4,5,6]
best = 0
para_C = []
para_degree =[]
for i in C:
    for j in degree:
        model = svm.SVC(C= i, kernel = 'poly', degree = j)
        model.fit(train_X,train_Y)
        predictionsSVM = model.predict(train_X)
        acc = accuracy_score(train_Y,predictionsSVM)
        if acc >= best:
            if acc==best:
                para_C.append(i)
                para_degree.append(j)    
            best = acc
            print('best score so far:',acc , '  Kernel:poly ', 'C:',i,' degree:',j)
para_C = set(para_C)
para_degree =set(para_degree)
modelGrid = GridSearchCV(svm.SVC(),[{'kernel': ['poly'], 'degree' : list(para_degree), 'C': list(para_C)}],
                     cv=10,
                     return_train_score = False
                    )
modelGrid.fit(train_X,train_Y)
df = pd.DataFrame(modelGrid.cv_results_)
df[['param_C','param_kernel','mean_test_score']].sort_values('mean_test_score',ascending = False)
df.sort_values('mean_test_score',ascending = False).head(10)
"""
### Comparing results from GridSearch and my own tuning 

GridSearchCV: Best mean results:  
* score : 0.809238    {'C': 4, 'degree': 3, 'kernel': 'poly'} 	



Tuning:
- best score so far: 0.8765432098765432   Kernel:poly  C: 4  degree: 4
- best score so far: 0.8765432098765432   Kernel:poly  C: 4  degree: 5
- best score so far: 0.8765432098765432   Kernel:poly  C: 4  degree: 6



"""
model = svm.SVC(C= 4, kernel = 'poly', degree = 3)
model.fit(train_X,train_Y)
predictionsSVM = model.predict(test_X)

results = pd.DataFrame({'PassengerId':test.PassengerId,'Survived':predictionsSVM})
results.to_csv('my_submission.csv', index=False)
print("Your submission was successfully saved!")