<jupyter_start><jupyter_text>**Titanic: Machine Learning from Disaster**This notebook is meant to guide us through exploratory data analysis and how to build a machine learning model using the famous Titanic dataset sourced from [Kaggle ](https://www.kaggle.com/c/titanic).Here, we will be predicting the survival of titanic passengers.The dataset provides information on passengers such as class, age, sex and survival.We'll be taking the following steps:0. Loading our data1. Exploratory data analysis2. Data visualization3. Data Preprocessing4. Building our machine learning model<jupyter_code>#Import our libraries
import numpy as np #linear algebra
import pandas as pd #data processing

#for data visualization
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.style

import seaborn as sns<jupyter_output><empty_output><jupyter_text>**0. Load the data**<jupyter_code>#since we're using Google Colab, we'll mount drive first
from google.colab import drive
drive.mount('/content/gdrive')
#load the file path
test_data_path = '/content/gdrive/My Drive/titanic/titanic/test.csv'
train_data_path = '/content/gdrive/My Drive/titanic/titanic/train.csv'

#Use pandas to read what's in it
test_data = pd.read_csv(test_data_path)
train_data = pd.read_csv(train_data_path)<jupyter_output><empty_output><jupyter_text>**1. Exploratory data analysis**Let's begin with exploratory data analysis. We will view the contents of our dataset.<jupyter_code>#Now we explore what's in our dataset
train_data.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB<jupyter_text>*From the above tells us the training set contains data on 891 passengers and 11 features (class, name, sex, etc)***PassengerId:** Id of each passenger **Survived:** Labelled 0 and 1 (dead and alive)**Pclass:** Passenger's class**Name:** Name of passenger**Sex:** Gender**Age:** Age**SibSp:** Number of siblings / spouses on the Titanic**Parch:** Number of parents / children on the Titanic**Ticket:** Ticket number**Fare:** Passenger's fare**Cabin:** Cabin number**Embarked:** Port of embarkation<jupyter_code>train_data.describe()<jupyter_output><empty_output><jupyter_text>*From above we see that in the training-set, 38% survived.**We also notice that some features containing missing values, like range as it's minimum value is 0.4.*<jupyter_code>#let's view the first 6 values of the dataset
train_data.head(6)<jupyter_output><empty_output><jupyter_text>*From above, we can notice that some data is missing (NaN).*Let's see what's missing:<jupyter_code>total = train_data.isnull().sum().sort_values(ascending=False)
percent_1 = train_data.isnull().sum()/train_data.isnull().count()*100
percent_2 = (round(percent_1, 1)).sort_values(ascending=False)
missing_data = pd.concat([total, percent_2], axis=1, keys=['Total', '%'])
missing_data.head(5)<jupyter_output><empty_output><jupyter_text>*We realize that Age has 177 missing values, embarked has 2 missing values while cabin has 687 missing values (which we are going to have to drop since 77% of it missing).* Now we ask ourselves, what features could contribute to a high survival rate?<jupyter_code>train_data.columns.values<jupyter_output><empty_output><jupyter_text>Let's calculate the percentage of women that survived.<jupyter_code>women = train_data.loc[train_data.Sex == 'female']["Survived"]
rate_women = sum(women)/len(women)

print("% of women who survived:", rate_women)<jupyter_output>% of women who survived: 0.7420382165605095<jupyter_text>*Here we see that about 75% of the women survived.* Let's calculate the percentage of men that survived.<jupyter_code>men = train_data.loc[train_data.Sex == 'male']["Survived"]
rate_men = sum(men)/len(men)

print("% of men who survived:", rate_men)<jupyter_output>% of men who survived: 0.18890814558058924<jupyter_text>*Here we see that about 18% of the men survived.* **2. Data visualization** ***Let's look at age and sex***<jupyter_code>survived = 'survived'
not_survived = 'not survived'
fig, axes = plt.subplots(nrows=1, ncols=2,figsize=(10, 4))
women = train_data[train_data['Sex']=='female']
men = train_data[train_data['Sex']=='male']
ax = sns.distplot(women[women['Survived']==1].Age.dropna(), bins=18, label = survived, ax = axes[0], kde =False)
ax = sns.distplot(women[women['Survived']==0].Age.dropna(), bins=40, label = not_survived, ax = axes[0], kde =False)
ax.legend()
ax.set_title('Female')
ax = sns.distplot(men[men['Survived']==1].Age.dropna(), bins=18, label = survived, ax = axes[1], kde = False)
ax = sns.distplot(men[men['Survived']==0].Age.dropna(), bins=40, label = not_survived, ax = axes[1], kde = False)
ax.legend()
_ = ax.set_title('Male')<jupyter_output><empty_output><jupyter_text>*We see that men have a high probability of survival between the ages of 18 - 30 years old and low between 5 and 18.**For women, the survival chances  are higher between 14 and 40.* ***Let's see if there's any correlation between ports embarked and survival***<jupyter_code>FacetGrid = sns.FacetGrid(train_data, row='Embarked', height=4.5, aspect=1.6)
FacetGrid.map(sns.pointplot, 'Survived', 'Sex', palette=None,  order=None, hue_order=None )
FacetGrid.add_legend()<jupyter_output><empty_output><jupyter_text>*Here, we notice the port they embark from seems to be correlated to survival.**Men have a high probability of survival if they were on Port C (Cherbourg), but a low probability if they were on S (Southampton) and Q (Queenstown).**Women have a high probability of survival if they were on port Q and S compared to port C.* ***Let's see if `Pclass` shows any correlation with survival***<jupyter_code>sns.barplot(x='Pclass', y='Survived', data=train_data)<jupyter_output><empty_output><jupyter_text>*Here, we see that people in class 1 had higher chances of survival compared to people in classes 2 and 3* **3. Data Preprocessing*****Let's drop the `PassengerId`  from the training set since it does not contribute to a person's survival probability.***<jupyter_code>train_data = train_data.drop(['PassengerId'], axis=1)<jupyter_output><empty_output><jupyter_text>***Let's also drop Cabin since it has a lot of missing values.***<jupyter_code>train_data = train_data.drop(['Cabin'], axis=1)
test_data = test_data.drop(['Cabin'], axis=1)<jupyter_output><empty_output><jupyter_text>**Since `Age `has missing values, let's create an that will fill the empty values with random values based on mean and standard deviation of the column.**<jupyter_code>data = [train_data, test_data]

for dataset in data:
    mean = train_data["Age"].mean()
    std = test_data["Age"].std()
    is_null = dataset["Age"].isnull().sum()
    # compute random numbers between the mean, std and is_null
    rand_age = np.random.randint(mean - std, mean + std, size = is_null)
    # fill NaN values in Age column with random values generated
    age_slice = dataset["Age"].copy()
    age_slice[np.isnan(age_slice)] = rand_age
    dataset["Age"] = age_slice
    dataset["Age"] = train_data["Age"].astype(int)
train_data["Age"].isnull().sum()<jupyter_output><empty_output><jupyter_text>***Since `Embarked` has just 2 missing values, we'll replace the empty values with the mode (most common values).***<jupyter_code>embarked_mode = train_data['Embarked'].mode()
data = [train_data, test_data]
for dataset in data:
    dataset['Embarked'] = dataset['Embarked'].fillna(embarked_mode)<jupyter_output><empty_output><jupyter_text>***Converting Features:*** ***Convert `Embarked` feature into numeric***<jupyter_code>ports = {"S": 0, "C": 1, "Q": 2}
data = [train_data, test_data]

for dataset in data:
    dataset['Embarked'] = dataset['Embarked'].map(ports)
    dataset['Embarked'] = dataset['Embarked'].fillna(0)
    dataset['Embarked'] = dataset['Embarked'].astype(int)<jupyter_output><empty_output><jupyter_text>***Convert `Sex` feature into numeric***<jupyter_code>genders = {"male": 0, "female": 1}
data = [train_data, test_data]

for dataset in data:
    dataset['Sex'] = dataset['Sex'].map(genders)<jupyter_output><empty_output><jupyter_text>***Convert `fare` feature to numeric***<jupyter_code>data = [train_data, test_data]

for dataset in data:
    dataset['Fare'] = dataset['Fare'].fillna(0)
    dataset['Fare'] = dataset['Fare'].astype(int)<jupyter_output><empty_output><jupyter_text>***Ticket***<jupyter_code>train_data['Ticket'].describe()<jupyter_output><empty_output><jupyter_text>***Since the `Ticket` attribute has 681 unique tickets, we will drop it from the dataset.***<jupyter_code>train_data = train_data.drop(['Ticket'], axis=1)
test_data = test_data.drop(['Ticket'], axis=1)<jupyter_output><empty_output><jupyter_text>***We will extract the titles from the `Names` attribute and create a new dataset with it. After which we're going to drop it.***<jupyter_code>data = [train_data, test_data]
titles = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}

for dataset in data:
    # extract titles
    dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
    # replace titles with a more common title or as Rare
    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')
    # convert titles into numbers
    dataset['Title'] = dataset['Title'].map(titles)
    # filling NaN with 0, to get safe
    dataset['Title'] = dataset['Title'].fillna(0)
train_data = train_data.drop(['Name'], axis=1)
test_data = test_data.drop(['Name'], axis=1)<jupyter_output><empty_output><jupyter_text>***```Fare``` is a float. We have to convert it from float to int64 using ```astype()``` function.***<jupyter_code>data = [train_data, test_data]

for dataset in data:
    dataset['Fare'] = dataset['Fare'].fillna(0)
    dataset['Fare'] = dataset['Fare'].astype(int)
train_data.info()
test_data.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 9 columns):
 #   Column       Non-Null Count  Dtype
---  ------       --------------  -----
 0   PassengerId  418 non-null    int64
 1   Pclass       418 non-null    int64
 2   Sex          418 non-null    int64
 3   Age          418 non-null    int64
 4   SibSp        418 non-null    int64
 5   Parch        418 non-null    int64
 6   Fare         418 non-null    int64
 7   Embarked     418 non-null    int64
 8   Title        418 non-null    int64
dtypes: int64(9)
memory usage: 29.5 KB<jupyter_text>***We've successfully converted all `object` and `float` in our test and training sets to `int64`, now we're ready to build our model.*** There are more preprocessing techniques you can try out on your own to boost the accuracy of your model. **4. Building Machine Learning Models**This is a classification problem since our required output variable is a category such as orange or yellow, spam or not spam, benign or malignant, in this case, 1 (alive) or 0 (dead).There are several classification models some of which are:*   Decision Trees*   Linear Classifiers such as: Logistic Regression, Naive Bayes*   Random Forest*   Nearest Neighbor, etc. Let's try **Logistic Regression**<jupyter_code>from sklearn.linear_model import LogisticRegression
X_train = train_data.drop("Survived", axis=1)
Y_train = train_data["Survived"]
X_test  = test_data.drop("PassengerId", axis=1).copy()
# Instantiate our model
logreg = LogisticRegression(max_iter = 4000)
# Fit our model to the training data
logreg.fit(X_train, Y_train)
# Predict on the test data
logreg_predictions = logreg.predict(X_test)


logreg_data = pd.read_csv(test_data_path)
logreg_data.insert((logreg_data.shape[1]),'Survived',logreg_predictions)

#logreg_data.to_csv('my_model.csv')
print(logreg_data)

#to calculate the accuracy of our model
acc_log = round(logreg.score(X_train, Y_train) * 100,2)<jupyter_output>PassengerId  Pclass  ... Embarked Survived
0            892       3  ...        Q        0
1            893       3  ...        S        1
2            894       2  ...        Q        0
3            895       3  ...        S        0
4            896       3  ...        S        1
..           ...     ...  ...      ...      ...
413         1305       3  ...        S        0
414         1306       1  ...        C        1
415         1307       3  ...        S        0
416         1308       3  ...        S        0
417         1309       3  ...        C        0

[418 rows x 12 columns]<jupyter_text>***Let's check the accuracy of our model***<jupyter_code>print(f"Accuracy: {acc_log}")<jupyter_output>The accuracy of our model is:
80.81
StarcoderdataJupyterStructuredCleanDedup