{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Titanic Notebook with explanations \n---\n\nNot being in the field, I struggled with this even though it is one of the first tutorial and very well designed.\nI chose to enrich my notebook with information coming from:\n - my experience (mainly mistakes! 😅)\n - other sections of Kaggle\n - DataCamp\n\nWe are going to use a Python library called `pandas`, a Python library for analysis and data manipulation.\n\nHere is a <a href=\"https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf\" target=\"_blank\">cheatsheet</a> for reference.\n<br>\n<a href=\"https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf\" target=\"_blank\"><img src=\"https://i.imgur.com/rcSXjEZ.png\" width=\"250px\"></a>\n\n## Setup the environment","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\nimport numpy as np   # linear algebra\nimport pandas as pd  # data processing, CSV file I/O (e.g. pd.read_csv)\nimport re            # regular expression\n\n# Data Visualization\npd.plotting.register_matplotlib_converters()\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport seaborn as sns\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Nice banner (hey, Bruce!)\nfrom IPython.display import clear_output\n#os.system(\"pip install art==5.6\")\n!pip install art --user\nclear_output()\n\nimport art\nart.tprint(\"Titanic Notebook\", font=\"cybermedium\")\n\n# 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\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-26T13:26:41.179489Z","iopub.execute_input":"2022-07-26T13:26:41.180460Z","iopub.status.idle":"2022-07-26T13:26:49.860264Z","shell.execute_reply.started":"2022-07-26T13:26:41.180420Z","shell.execute_reply":"2022-07-26T13:26:49.859010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train data\nThe training file `train_data.csv` contains both numeric and non-numeric columns.<br>\nWe will see how to leverage non-numeric values by \"transposing\" them into numeric ones in a later chapter...","metadata":{}},{"cell_type":"code","source":"# Train data contains more columns, including the \"Survived\" column\ntrain_data = pd.read_csv(\"/kaggle/input/titanic/train.csv\")\nprint(\"(Rows, columns) = \", train_data.shape)\nprint()\n\nprint(train_data.columns)\nprint()\n\ntrain_data.head()    # <-- not visible in the output, only the last statement is displayed (see tail() below). Here, use `print(...)` instead as above\ntrain_data.tail()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:49.862860Z","iopub.execute_input":"2022-07-26T13:26:49.863318Z","iopub.status.idle":"2022-07-26T13:26:49.890210Z","shell.execute_reply.started":"2022-07-26T13:26:49.863268Z","shell.execute_reply":"2022-07-26T13:26:49.889177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test data\nContains same columns except the \"Survived\" one","metadata":{}},{"cell_type":"code","source":"test_data = pd.read_csv(\"/kaggle/input/titanic/test.csv\")\nprint(test_data.columns)\ntest_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:49.891850Z","iopub.execute_input":"2022-07-26T13:26:49.892282Z","iopub.status.idle":"2022-07-26T13:26:49.913867Z","shell.execute_reply.started":"2022-07-26T13:26:49.892244Z","shell.execute_reply":"2022-07-26T13:26:49.913096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Test data contains 418 lines\ntest_data.describe()     # only displays numerical value","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:49.915585Z","iopub.execute_input":"2022-07-26T13:26:49.916163Z","iopub.status.idle":"2022-07-26T13:26:49.945695Z","shell.execute_reply.started":"2022-07-26T13:26:49.916131Z","shell.execute_reply":"2022-07-26T13:26:49.944732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Exploring the data: \"Women and children first!\"\n\nLet's first study: Women ♀️ against Men ♂️","metadata":{}},{"cell_type":"markdown","source":"### Women 👩‍🦱","metadata":{}},{"cell_type":"code","source":"# Filter only female passengers using `loc`\nwomen = train_data.loc[train_data.Sex == 'female']\nwomen.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:49.947061Z","iopub.execute_input":"2022-07-26T13:26:49.947481Z","iopub.status.idle":"2022-07-26T13:26:49.966554Z","shell.execute_reply.started":"2022-07-26T13:26:49.947440Z","shell.execute_reply":"2022-07-26T13:26:49.965637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Does the gender completely determine the survival? \n# (i.e. being a female ensures survival, being male means certain death)\nwomen = train_data.loc[train_data.Sex == 'female'][\"Survived\"]\nrate_women = sum(women)/len(women)\nprint(f\"Women ♀️ who survived: {100 * rate_women:.2f} %\")    # this syntax is called 'Formatted string litterals': https://docs.python.org/3/tutorial/inputoutput.html#tut-f-strings\n\nplt.title(\"Women ♀️ who survived\", size=16)\nwomen.value_counts().plot.pie(colors=[\"mistyrose\", \"black\"], shadow=True)   # mistyROSE?! Got this one? 😜","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:49.968336Z","iopub.execute_input":"2022-07-26T13:26:49.968640Z","iopub.status.idle":"2022-07-26T13:26:50.078719Z","shell.execute_reply.started":"2022-07-26T13:26:49.968614Z","shell.execute_reply":"2022-07-26T13:26:50.077742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Men 👨‍🦰","metadata":{}},{"cell_type":"code","source":"\nmen = train_data.loc[train_data.Sex == 'male'][\"Survived\"]\nrate_men = sum(men)/len(men)\nprint(\"Men ♂️ who survived:\", round(100 * rate_men, 2), \"%\")\n\nplt.title(\"Men ♂️ who survived\", size=16)\nmen.value_counts().plot.pie(colors=[\"black\", \"dodgerblue\"], shadow=True)","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:50.080125Z","iopub.execute_input":"2022-07-26T13:26:50.081198Z","iopub.status.idle":"2022-07-26T13:26:50.232364Z","shell.execute_reply.started":"2022-07-26T13:26:50.081154Z","shell.execute_reply":"2022-07-26T13:26:50.231351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### What about age-wise: 👶 vs 🧑 vs 👨 vs 👴?\nNow, look at how age is related to the survival rate.<br>\n<i>Although I used male emoji, the analysis will be performed gender-free.</i>","metadata":{}},{"cell_type":"code","source":"# labels = [\"0-2\", \"2-13\", \"13-18\", \"18-34\", \"35-49\", \"50-65\", \"65+\"]\ntrain_data[\"AgeCategory\"] = train_data[\"Age\"].map(lambda a: \" 0-2\"   if (0 <= a < 2)  else \n                                                            \" 2-5\"   if (2 <= a < 5) else \n                                                            \" 6-13\"  if (6 <= a < 13) else \n                                                            \"13-18\" if (13 <= a < 18) else \n                                                            \"18-34\" if (18 <= a < 34) else \n                                                            \"35-49\" if (35 <= a < 49) else \n                                                            \"50-65\" if (50 <= a < 65) else \n                                                            \"65+\"   if (a >= 65) else \"Unknown\")\n\nage_list = train_data[\"AgeCategory\"].drop_duplicates().sort_values().reset_index(drop=True)\n\nage_distribution =  pd.DataFrame({\n    \"AgeCategory\": age_list, \n    \"Male\": age_list.map(lambda age: train_data.loc[(train_data[\"AgeCategory\"] == age) & (train_data[\"Sex\"] == \"male\"), \"AgeCategory\"].count()), \n    \"Female\": age_list.map(lambda age: train_data.loc[(train_data[\"AgeCategory\"] == age) & (train_data[\"Sex\"] == \"female\"), \"AgeCategory\"].count()), \n    \"Total\": age_list.map(lambda age: train_data.loc[train_data[\"AgeCategory\"] == age, \"AgeCategory\"].count()),\n    \"MaleSurvivors\": age_list.map(lambda age: train_data.loc[(train_data[\"AgeCategory\"] == age) & (train_data[\"Sex\"] == \"male\")][\"Survived\"].sum()),\n    \"FemaleSurvivors\": age_list.map(lambda age: train_data.loc[(train_data[\"AgeCategory\"] == age) & (train_data[\"Sex\"] == \"female\")][\"Survived\"].sum()),\n    \"Survivors\": age_list.map(lambda age: train_data.loc[train_data[\"AgeCategory\"] == age][\"Survived\"].sum()) })\n\nage_distribution[\"MaleRate\"]   = round(100 * age_distribution[\"MaleSurvivors\"] / age_distribution[\"Male\"], 1)\nage_distribution[\"FemaleRate\"] = round(100 * age_distribution[\"FemaleSurvivors\"] / age_distribution[\"Female\"], 1)\nage_distribution[\"Rate\"]       = round(100 * age_distribution[\"Survivors\"] / age_distribution[\"Total\"], 1)\n\nprint(age_distribution[[\"AgeCategory\", \"Male\", \"Female\", \"MaleRate\", \"FemaleRate\", \"Rate\"]].sort_values(by=\"AgeCategory\", ascending=True))\nprint()\n\n# plt.title(\"Age distribution of Passengers\", size=16)\n# train_data[\"AgeCategory\"].value_counts().plot.bar()\n\nfig, ax = plt.subplots()\nlabels = age_distribution[\"AgeCategory\"]\nwidth = 0.65  \n\nax.bar(labels, age_distribution[\"Total\"] - age_distribution[\"Survivors\"], width, color=\"black\", label=\"Dead\")\nax.bar(labels, age_distribution[\"Survivors\"], width, bottom=age_distribution[\"Total\"] - age_distribution[\"Survivors\"], color=\"tan\", label=\"Survivors\")\n\nax.set_title('Age distribution of Survivors')\nax.legend()\n\n# Texts on top of bars\nfor i in age_distribution.index:\n    plt.text(i - 0.3, age_distribution.at[i, \"Total\"] + 5, str(age_distribution.at[i, \"Rate\"]) + \"%\")\n    \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:50.234366Z","iopub.execute_input":"2022-07-26T13:26:50.235170Z","iopub.status.idle":"2022-07-26T13:26:50.498713Z","shell.execute_reply.started":"2022-07-26T13:26:50.235125Z","shell.execute_reply":"2022-07-26T13:26:50.497781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusion\n<ul>\n    <li>A large majority of babies and very young children (between 0 and 2 years old) survived the shipwreck</li>\n    <li>Girls ranging from 6 to 13 years old has a unusual low rate of survival: both much lower than other females AND lower than the males of same age</li>\n    <li>Mortality is (surprisingly) quite high especially for boys in the 13-18 years old range! Even lower than adult's survival rate with a dreadful 10%! 😨</li>\n    <li>Another finding is that survival is in reverse order (with the exception of 65+) from adults: 50-65 survived significantly more than 18-34.<br>\n    It would be interesting to know whether other factors could explain this (for instance, seniors tend to have better tickets hence better places in rowboats, ... ?)</li>\n</ul>\n\nAfter this quick study, we can acknowledge that the old saying \"Women and children first!\" is actually rather true!\n    ","metadata":{}},{"cell_type":"markdown","source":"# A bit of theory 👨‍🏫\n---\n## Random forest model: a machine learning (ML) model\n\nThis model is constructed of several \"trees\" (there are three trees in the picture below, but we'll construct 100!) that will individually consider each passenger's data and vote on whether the individual survived. Then, the random forest model makes a democratic decision: the outcome with the most votes wins!\n\n![](https://i.imgur.com/AC9Bq63.png)","metadata":{}},{"cell_type":"markdown","source":"# Working on train_data 🏋\n---","metadata":{}},{"cell_type":"code","source":"# Get statistics about train_data.csv\ntrain_data.describe()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:50.500211Z","iopub.execute_input":"2022-07-26T13:26:50.500487Z","iopub.status.idle":"2022-07-26T13:26:50.537645Z","shell.execute_reply.started":"2022-07-26T13:26:50.500462Z","shell.execute_reply":"2022-07-26T13:26:50.536713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Only 183 records contains data in each and every column\ntrain_data.dropna(axis=\"index\").describe()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:50.539930Z","iopub.execute_input":"2022-07-26T13:26:50.540249Z","iopub.status.idle":"2022-07-26T13:26:50.574578Z","shell.execute_reply.started":"2022-07-26T13:26:50.540222Z","shell.execute_reply":"2022-07-26T13:26:50.573598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# From Name column to a new \"Title\" feature\n\nName itself is sort of *useless* but it contains the Title.\nTo use it with `RandomForestClassifier` (see below), it seems necessary to somehow convert string values to numeric values.\n\nSeems interesting enough, let's extract this as a new column using `split` then extend our DataFrame with`assign` for both train_data and test_data\n\n*Reminder*: use the <a href=\"https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf\" target=\"_blank\">cheatsheet</a> to get familiar with `pandas` functions","metadata":{}},{"cell_type":"code","source":"#-------------------------------------------------------------------------------\n# Simple string > int conversion\n#-------------------------------------------------------------------------------\n# train_data[\"Survived\"] = train_data[\"Survived\"].map(lambda s: int(s))\n\n#-------------------------------------------------------------------------------\n# Extend Train data with a 'Title' column\n#-------------------------------------------------------------------------------\n# Legacy way:\n#   lastname_data = pd.DataFrame({\"Rest\": train_data[\"Name\"].str.split(\",\", expand=True)[1]})\n#   title_data = pd.DataFrame({\"Title\": lastname_data[\"Rest\"].str.split(\".\", expand=True)[0]})\n#   train_data = train_data.assign(Title=title_data)\n#   train_data[\"Title\"] = train_data[\"Name\"].map(lambda t: t.split(\",\")[1].split(\".\")[0])\n\ntrain_data[\"Title\"] = train_data[\"Name\"].map(lambda t: (re.search(\",\\s([A-Z][a-z]*)?\", t).group(1) or \"\").strip())\ntrain_data.head()\n\n#-------------------------------------------------------------------------------\n# Encode 'Title' as numeric \n#-------------------------------------------------------------------------------\n# so that RandomForestClassifier can be used on it\ntitle_map = train_data[\"Title\"].drop_duplicates().reset_index(drop=True)\nprint(title_map)\nprint()\n\n# Let's define an auxiliary function\ndef title_to_numeric(t):\n    result = title_map.loc[title_map.str.contains(t)].index\n    return result.values[0] # if result.any() else -1\n\nprint(\"'Miss' value is converted to the number: \" + str(title_to_numeric(\"Miss\")))\nprint(\"'Capt' value is converted to the number: \" + str(title_to_numeric(\"Capt\")))\nprint()\n\n#-------------------------------------------------------------------------------\n# Extend Train data with a 'TitleNum' column\n#-------------------------------------------------------------------------------\n\nfor i in train_data.index:\n    title = train_data.at[i, \"Title\"]\n    try:\n        train_data.at[i, \"TitleNum\"] = title_to_numeric(title)\n    except:\n        train_data.at[i, \"TitleNum\"] = -1\n    \ntrain_data.describe()\n","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:50.575696Z","iopub.execute_input":"2022-07-26T13:26:50.576100Z","iopub.status.idle":"2022-07-26T13:26:50.994569Z","shell.execute_reply.started":"2022-07-26T13:26:50.576067Z","shell.execute_reply":"2022-07-26T13:26:50.993628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## \"Title\" column exploration\nNow that we have all the titles, let's explore this new data!","metadata":{}},{"cell_type":"code","source":"title_explore = train_data[[\"Title\", \"Survived\"]]\n\ntitle_explore = title_explore.groupby([\"Title\"]).sum()\ntitle_explore[\"Count\"] = train_data[\"Title\"].value_counts()\ntitle_explore[\"SurvivalRate\"] = round(100 * title_explore[\"Survived\"] / title_explore[\"Count\"], 1)\n\ntitle_explore.sort_values(\"SurvivalRate\")","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:50.996194Z","iopub.execute_input":"2022-07-26T13:26:50.996629Z","iopub.status.idle":"2022-07-26T13:26:51.016949Z","shell.execute_reply.started":"2022-07-26T13:26:50.996587Z","shell.execute_reply":"2022-07-26T13:26:51.015957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Perform the same action with \"Title\" and \"TitleNum\" on `test_data`","metadata":{}},{"cell_type":"code","source":"#-------------------------------------------------------------------------------\n# Extend Test data with a 'Title' column\n#-------------------------------------------------------------------------------\ntest_data[\"Title\"] = test_data[\"Name\"].map(lambda t: (re.search(\",\\s([A-Z][a-z]*)?\", t).group(1) or \"\").strip())\ntest_data.head()\n\n#-------------------------------------------------------------------------------\n# Extend Test data with a 'TitleNum' column\n#-------------------------------------------------------------------------------\n\nfor i in test_data.index:\n    title = test_data.at[i, \"Title\"]\n    try:\n        test_data.at[i, \"TitleNum\"] = title_to_numeric(title)\n    except:\n        test_data.at[i, \"TitleNum\"] = -1\n    \ntest_data.describe()","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:51.018107Z","iopub.execute_input":"2022-07-26T13:26:51.019110Z","iopub.status.idle":"2022-07-26T13:26:51.208678Z","shell.execute_reply.started":"2022-07-26T13:26:51.019067Z","shell.execute_reply":"2022-07-26T13:26:51.207637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dealing with Missing Values \n📘 <a href=\"https://www.kaggle.com/code/alexisbcook/missing-values?kernelSessionId=79127568\" target=\"_blank\">Missing Values notebook by Alexis Cook & DanB</a>","metadata":{}},{"cell_type":"code","source":"# [Train data] Missing values per column\nprint(\"Missing values in Train data\\n\" + str(train_data.isnull().sum()))\nprint()\n\n# Fill messing age with mean value\n#train_data[\"Age\"] = train_data[\"Age\"].fillna(29)   <-- this is one way but a better one is using `median` and `inplace = True` like below\ntrain_data[\"Age\"].fillna(train_data[\"Age\"].median(), inplace = True)\ntrain_data[\"Cabin\"].fillna('', inplace = True)\ntrain_data[\"Embarked\"].fillna('', inplace = True)\n\nprint(\"Train data after mising-value processing\\n\" + str(train_data.isnull().sum()))\nprint()\n","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:51.209954Z","iopub.execute_input":"2022-07-26T13:26:51.210333Z","iopub.status.idle":"2022-07-26T13:26:51.222271Z","shell.execute_reply.started":"2022-07-26T13:26:51.210303Z","shell.execute_reply":"2022-07-26T13:26:51.221679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# [Test data] Missing values per column\nprint(\"Missing values in Test data\\n\" + str(test_data.isnull().sum()))\nprint()\n\n# Fill messing age with mean value\ntest_data[\"Age\"].fillna(test_data[\"Age\"].median(), inplace = True)\ntest_data[\"Cabin\"].fillna('', inplace = True)\ntest_data[\"Fare\"].fillna(test_data[\"Fare\"].median(), inplace = True)\ntest_data[\"Embarked\"].fillna('', inplace = True)\n\nprint(\"Test data after mising-value processing\\n\" + str(test_data.isnull().sum()))","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:51.223278Z","iopub.execute_input":"2022-07-26T13:26:51.223711Z","iopub.status.idle":"2022-07-26T13:26:51.236236Z","shell.execute_reply.started":"2022-07-26T13:26:51.223674Z","shell.execute_reply":"2022-07-26T13:26:51.235301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Let's predict! 🔮\n---\n[<img src=\"https://i.imgur.com/uhfugn1.png\" width=\"640\"/>](https://i.imgur.com/uhfugn1.png)","metadata":{}},{"cell_type":"markdown","source":"## Correlation\nLet's find out which columns makes the most sense when it comes to survival rate","metadata":{}},{"cell_type":"code","source":"train_data.corr()[\"Survived\"]","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:51.237573Z","iopub.execute_input":"2022-07-26T13:26:51.237910Z","iopub.status.idle":"2022-07-26T13:26:51.250633Z","shell.execute_reply.started":"2022-07-26T13:26:51.237882Z","shell.execute_reply":"2022-07-26T13:26:51.249738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The code cell below (originally) looks for patterns in four different columns (**\"Pclass\"**, **\"Sex\"**, **\"SibSp\"**, and **\"Parch\"**) of the data. \n\nFollow the correlation results above, we decided to keep the colums:\n* **\"Pclass\"**\n* **\"Fare\"**\n* **\"TitleNum\"**  (which contains much information including: Age, Sex but also social-ladder aspects)\n\nWe construct the trees in the random forest model based on patterns in the **train.csv** file, before generating predictions for the passengers in **test.csv**. \nThe code also saves these new predictions in a CSV file **submission.csv**.","metadata":{}},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestClassifier\n\n#-------------------\n# Fitting ML\n#-------------------\n\ny = train_data[\"Survived\"]\n\n# 2022-06-09: Version with more features\n# all_features = [\"Pclass\", \"Name\", \"Sex\", \"Age\", \"SibSp\", \"Parch\", \"Ticket\", \"Fare\", \"Cabin\", \"Embarked\"]\n# min_features = [\"Pclass\", \"Sex\", \"SibSp\", \"Parch\"]\n# features = [\"Pclass\", \"Age\", \"Sex\", \"SibSp\", \"Parch\"]\nfeatures = [\"Pclass\", \"Fare\", \"TitleNum\"]\nX = pd.get_dummies(train_data[features])\nX_test = pd.get_dummies(test_data[features])\n\nmodel = RandomForestClassifier(n_estimators=100, max_depth=len(features)+1, random_state=1)\n\nmodel.fit(X, y)\npredictions = model.predict(X_test)\n\n#-------------------\n# Fit score\n#-------------------\n\nX_train = pd.get_dummies(train_data[features])\nchecks = model.predict(X_train)\n\nfit = pd.DataFrame({'PassengerId': train_data.PassengerId, 'PredictSurvived': train_data.Survived, 'HasSurvived': checks})\nfit_score = fit.PredictSurvived == fit.HasSurvived\n# print('Fit score on train_data:' + str(sum(fit_score) / len(fit_score)))\nart.tprint('Fit score ', font=\"white_bubble\")\nprint(f'{100 * sum(fit_score) / len(fit_score):.2f} %')\nprint()\n\n#-------------------\n# Submission!\n#-------------------\n\noutput = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})\noutput.head()\n\noutput.to_csv('submission.csv', index=False)\nprint(\"Your submission was successfully saved!\")","metadata":{"execution":{"iopub.status.busy":"2022-07-26T13:26:51.252350Z","iopub.execute_input":"2022-07-26T13:26:51.253436Z","iopub.status.idle":"2022-07-26T13:26:51.460837Z","shell.execute_reply.started":"2022-07-26T13:26:51.253388Z","shell.execute_reply":"2022-07-26T13:26:51.459924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Going further 🎯\n---\n## Fit score VS Test score\nSo, we get a **fit score** (on train data) of about **91%** whereas our **test score** is barely at **78%**.\nWhy such a gap? Is this **overfitting**?\n\n## How to go even further? 🚀\n@mirfanazam with a *CatBoost* classifier managed to go (a bit) further\nhttps://www.kaggle.com/code/mirfanazam/prophet-titanic/notebook\n\n@blue7red managed to achieve *81,5%* with an *AutoGluon* approach\nhttps://www.kaggle.com/code/rhythmcam/titanic-autogluon-label-encoding/notebook","metadata":{}}]}