{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Import necessary modules" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ ":228: RuntimeWarning: scipy._lib.messagestream.MessageStream size changed, may indicate binary incompatibility. Expected 56 from C header, got 64 from PyObject\n" ] } ], "source": [ "import numpy as np\n", "import pandas as pd\n", "import scipy as sp\n", "import matplotlib.pyplot as plt\n", "import sklearn as sk\n", "import datetime\n", "import calendar\n", "from jupyter_dash import JupyterDash\n", "import dash\n", "from dash import Dash, html, dcc, Input, Output\n", "import plotly.express as px\n", "from plotly.subplots import make_subplots\n", "import plotly.graph_objects as go\n", "import requests\n", "import io\n", "from plotly.subplots import make_subplots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Set up Google Cloud BigQuery Request" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zsh:1: command not found: gcloud\r\n" ] } ], "source": [ "from google.cloud import bigquery\n", "!export GOOGLE_APPLICATION_CREDENTIALS=\"cse6242project-377400-2f98c9def7f8.json\"\n", "!gcloud auth activate-service-account --key-file cse6242project-377400-2f98c9def7f8.json" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "os.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"]=\"cse6242project-377400-2f98c9def7f8.json\"" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Initialize a BigQuery client\n", "client = bigquery.Client()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "table_ref = client.dataset('cse6242gbq').table('counts_table')\n", "table = client.get_table(table_ref)\n", "\n", "schema_df = pd.DataFrame([field.to_api_repr() for field in table.schema])" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
datetimeviewcarmotorcyclelarge_vehicle
02023-02-1511:19:11View_from_Tuas_Checkpoint1509
12023-02-1711:21:04View_from_Tuas_Checkpoint1704
22023-02-1715:13:21View_from_Tuas_Checkpoint1805
32023-02-2013:14:32View_from_Tuas_Checkpoint1507
42023-02-2014:18:19View_from_Tuas_Checkpoint1505
\n", "
" ], "text/plain": [ " date time view car motorcycle \\\n", "0 2023-02-15 11:19:11 View_from_Tuas_Checkpoint 15 0 \n", "1 2023-02-17 11:21:04 View_from_Tuas_Checkpoint 17 0 \n", "2 2023-02-17 15:13:21 View_from_Tuas_Checkpoint 18 0 \n", "3 2023-02-20 13:14:32 View_from_Tuas_Checkpoint 15 0 \n", "4 2023-02-20 14:18:19 View_from_Tuas_Checkpoint 15 0 \n", "\n", " large_vehicle \n", "0 9 \n", "1 4 \n", "2 5 \n", "3 7 \n", "4 5 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "query = \"\"\"\n", " SELECT * \n", " FROM `cse6242project-377400.cse6242gbq.counts_table` \n", " \"\"\"\n", "df = client.query(query).to_dataframe()\n", "df.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data Preprocessing" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
datetimeviewcarmotorcyclelarge_vehicle
02023-02-1422:36:03View_from_Woodlands_Causeway_Towards_Johor200
12023-02-1423:14:34View_from_Woodlands_Checkpoint_Towards_BKE000
22023-02-1422:36:03View_from_Woodlands_Checkpoint_Towards_BKE301
32023-02-1422:36:03View_from_Second_Link_at_Tuas001
42023-02-1423:14:34View_from_Second_Link_at_Tuas006
\n", "
" ], "text/plain": [ " date time view car \\\n", "0 2023-02-14 22:36:03 View_from_Woodlands_Causeway_Towards_Johor 2 \n", "1 2023-02-14 23:14:34 View_from_Woodlands_Checkpoint_Towards_BKE 0 \n", "2 2023-02-14 22:36:03 View_from_Woodlands_Checkpoint_Towards_BKE 3 \n", "3 2023-02-14 22:36:03 View_from_Second_Link_at_Tuas 0 \n", "4 2023-02-14 23:14:34 View_from_Second_Link_at_Tuas 0 \n", "\n", " motorcycle large_vehicle \n", "0 0 0 \n", "1 0 0 \n", "2 0 1 \n", "3 0 1 \n", "4 0 6 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "df = df.sort_values(by=['date']).reset_index(drop=True)\n", "display(df.head(5))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(11592, 6)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
datetimeviewcarlarge_vehicledayvehicle
115872023-04-1202:33:57View_from_Woodlands_Causeway_Towards_Johor_to_jh00Wednesday0
115882023-04-1203:05:44View_from_Woodlands_Causeway_Towards_Johor_to_jh00Wednesday0
115892023-04-1203:33:38View_from_Woodlands_Causeway_Towards_Johor_to_jh00Wednesday0
115902023-04-1204:33:29View_from_Woodlands_Causeway_Towards_Johor_to_jh00Wednesday0
115912023-04-1200:09:35View_from_Tuas_Checkpoint_to_jh00Wednesday0
\n", "
" ], "text/plain": [ " date time view \\\n", "11587 2023-04-12 02:33:57 View_from_Woodlands_Causeway_Towards_Johor_to_jh \n", "11588 2023-04-12 03:05:44 View_from_Woodlands_Causeway_Towards_Johor_to_jh \n", "11589 2023-04-12 03:33:38 View_from_Woodlands_Causeway_Towards_Johor_to_jh \n", "11590 2023-04-12 04:33:29 View_from_Woodlands_Causeway_Towards_Johor_to_jh \n", "11591 2023-04-12 00:09:35 View_from_Tuas_Checkpoint_to_jh \n", "\n", " car large_vehicle day vehicle \n", "11587 0 0 Wednesday 0 \n", "11588 0 0 Wednesday 0 \n", "11589 0 0 Wednesday 0 \n", "11590 0 0 Wednesday 0 \n", "11591 0 0 Wednesday 0 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "print(df.shape)\n", "df['date'] = pd.to_datetime(df['date'], format = \"%Y-%m-%d\")\n", "df['day'] = df['date'].dt.day_name()\n", "df.drop(columns=['motorcycle'], axis=1, inplace=True)\n", "df['vehicle'] = df['car'] + df['large_vehicle']\n", "display(df.tail(5))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['View_from_Woodlands_Causeway_Towards_Johor',\n", " 'View_from_Woodlands_Checkpoint_Towards_BKE',\n", " 'View_from_Second_Link_at_Tuas', 'View_from_Tuas_Checkpoint',\n", " 'View_from_Tuas_Checkpoint_to_sg',\n", " 'View_from_Second_Link_at_Tuas_to_jh',\n", " 'View_from_Woodlands_Checkpoint_Towards_BKE_to_jh',\n", " 'View_from_Woodlands_Checkpoint_Towards_BKE_to_sg',\n", " 'View_from_Second_Link_at_Tuas_to_sg',\n", " 'View_from_Tuas_Checkpoint_to_jh',\n", " 'View_from_Woodlands_Causeway_Towards_Johor_to_jh',\n", " 'View_from_Woodlands_Causeway_Towards_Johor_to_sg'], dtype=object)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display(df['view'].unique())" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
datetimeviewcarlarge_vehicledayvehicle
02023-02-1422:36:03View_from_Woodlands_Causeway_Towards_Johor20Tuesday2
12023-02-1423:14:34View_from_Woodlands_Checkpoint_Towards_BKE00Tuesday0
22023-02-1422:36:03View_from_Woodlands_Checkpoint_Towards_BKE31Tuesday4
32023-02-1422:36:03View_from_Second_Link_at_Tuas01Tuesday1
42023-02-1423:14:34View_from_Second_Link_at_Tuas06Tuesday6
52023-02-1422:36:03View_from_Tuas_Checkpoint20Tuesday2
62023-02-1423:14:34View_from_Tuas_Checkpoint10Tuesday1
72023-02-1423:14:34View_from_Woodlands_Causeway_Towards_Johor00Tuesday0
82023-02-1501:14:01View_from_Second_Link_at_Tuas03Wednesday3
92023-02-1507:14:45View_from_Woodlands_Checkpoint_Towards_BKE22Wednesday4
\n", "
" ], "text/plain": [ " date time view car \\\n", "0 2023-02-14 22:36:03 View_from_Woodlands_Causeway_Towards_Johor 2 \n", "1 2023-02-14 23:14:34 View_from_Woodlands_Checkpoint_Towards_BKE 0 \n", "2 2023-02-14 22:36:03 View_from_Woodlands_Checkpoint_Towards_BKE 3 \n", "3 2023-02-14 22:36:03 View_from_Second_Link_at_Tuas 0 \n", "4 2023-02-14 23:14:34 View_from_Second_Link_at_Tuas 0 \n", "5 2023-02-14 22:36:03 View_from_Tuas_Checkpoint 2 \n", "6 2023-02-14 23:14:34 View_from_Tuas_Checkpoint 1 \n", "7 2023-02-14 23:14:34 View_from_Woodlands_Causeway_Towards_Johor 0 \n", "8 2023-02-15 01:14:01 View_from_Second_Link_at_Tuas 0 \n", "9 2023-02-15 07:14:45 View_from_Woodlands_Checkpoint_Towards_BKE 2 \n", "\n", " large_vehicle day vehicle \n", "0 0 Tuesday 2 \n", "1 0 Tuesday 0 \n", "2 1 Tuesday 4 \n", "3 1 Tuesday 1 \n", "4 6 Tuesday 6 \n", "5 0 Tuesday 2 \n", "6 0 Tuesday 1 \n", "7 0 Tuesday 0 \n", "8 3 Wednesday 3 \n", "9 2 Wednesday 4 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "transfer = {\"View_from_Second_Link_at_Tuas_to_sg\": 'Johor-Tuas', \n", " \"View_from_Second_Link_at_Tuas_to_jh\": 'Tuas-Johor',\n", " \"View_from_Tuas_Checkpoint_to_sg\": 'Johor-Tuas',\n", " \"View_from_Tuas_Checkpoint_to_jh\": 'Tuas-Johor',\n", " \"View_from_Woodlands_Causeway_Towards_Johor_to_sg\": 'Johor-Woodlands',\n", " \"View_from_Woodlands_Causeway_Towards_Johor_to_jh\": 'Woodlands-Johor',\n", " \"View_from_Woodlands_Checkpoint_Towards_BKE_to_sg\": 'Johor-Woodlands',\n", " \"View_from_Woodlands_Checkpoint_Towards_BKE_to_jh\": 'Woodlands-Johor'}\n", "\n", "new_table = df.replace({'view':transfer})\n", "display(new_table.head(10))" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['View_from_Woodlands_Causeway_Towards_Johor'\n", " 'View_from_Woodlands_Checkpoint_Towards_BKE'\n", " 'View_from_Second_Link_at_Tuas' 'View_from_Tuas_Checkpoint' 'Johor-Tuas'\n", " 'Tuas-Johor' 'Woodlands-Johor' 'Johor-Woodlands']\n" ] } ], "source": [ "print(new_table.loc[:,'view'].unique())" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(11592, 7)\n", "(9808, 7)\n" ] } ], "source": [ "options = ['Johor-Woodlands','Woodlands-Johor','Johor-Tuas','Tuas-Johor']\n", "print(new_table.shape)\n", "\n", "final_df = new_table[new_table['view'].isin(options)]\n", "print(final_df.shape)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11:19:11\n" ] }, { "data": { "text/plain": [ "'11:00'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from datetime import datetime, timedelta\n", "\n", "tim = df.loc[30,['time']][0]\n", "print(tim)\n", "\n", "def hour_rounder(t):\n", " if int(t.minute)>= 30:\n", " time_1 = str(int(t.hour)+1)\n", " if len(time_1) == 1:\n", " return \"0\"+time_1+\":00\"\n", " else:\n", " return str(time_1)+\":00\"\n", " else:\n", " if len(str(t.hour)) == 1:\n", " return \"0\"+str(t.hour)+\":00\"\n", " else:\n", " return str(t.hour)+\":00\"\n", "hour_rounder(tim)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "scrolled": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/w8/7fvtd_nn7235fgdf50g59c5h0000gn/T/ipykernel_34059/2962692662.py:1: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " final_df.loc[:,'hour'] = final_df.loc[:,'time'].apply(hour_rounder)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
datetimeviewcarlarge_vehicledayvehiclehour
17202023-03-0718:10:53Johor-Tuas10Tuesday118:00
17212023-03-0721:25:17Tuas-Johor01Tuesday121:00
17222023-03-0718:15:53Woodlands-Johor80Tuesday818:00
17232023-03-0718:15:53Johor-Woodlands00Tuesday018:00
17242023-03-0723:14:49Johor-Tuas03Tuesday323:00
\n", "
" ], "text/plain": [ " date time view car large_vehicle day \\\n", "1720 2023-03-07 18:10:53 Johor-Tuas 1 0 Tuesday \n", "1721 2023-03-07 21:25:17 Tuas-Johor 0 1 Tuesday \n", "1722 2023-03-07 18:15:53 Woodlands-Johor 8 0 Tuesday \n", "1723 2023-03-07 18:15:53 Johor-Woodlands 0 0 Tuesday \n", "1724 2023-03-07 23:14:49 Johor-Tuas 0 3 Tuesday \n", "\n", " vehicle hour \n", "1720 1 18:00 \n", "1721 1 21:00 \n", "1722 8 18:00 \n", "1723 0 18:00 \n", "1724 3 23:00 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "final_df.loc[:,'hour'] = final_df.loc[:,'time'].apply(hour_rounder)\n", "\n", "display(final_df.head(5))" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
dayhourviewvehicle
0Friday00:00Johor-Tuas3
1Friday01:00Johor-Tuas15
2Friday02:00Johor-Tuas17
3Friday03:00Johor-Tuas6
4Friday04:00Johor-Tuas11
\n", "
" ], "text/plain": [ " day hour view vehicle\n", "0 Friday 00:00 Johor-Tuas 3\n", "1 Friday 01:00 Johor-Tuas 15\n", "2 Friday 02:00 Johor-Tuas 17\n", "3 Friday 03:00 Johor-Tuas 6\n", "4 Friday 04:00 Johor-Tuas 11" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "final_table = final_df.groupby(['view', 'day', 'hour']).sum().reset_index().loc[:,['day', 'hour','view', 'vehicle']]\n", "display(final_table.head(5))" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def peak_hours(t):\n", " peak = ['07:00', \"08:00\", '09:00', \"17:00\", \"18:00\", \"19:00\"]\n", " if t in peak:\n", " return 1\n", " else:\n", " return 0" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "def weekend(w):\n", " end = ['Saturday', 'Sunday']\n", " if w in end:\n", " return 1\n", " else:\n", " return 0" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "def vehicle_cat(v):\n", " if v >= 0 and v < 20:\n", " return 0\n", " elif v >= 20 and v < 50:\n", " return 1\n", " elif v >= 50 and v < 80:\n", " return 2\n", " elif v >= 80 and v < 120:\n", " return 3\n", " else:\n", " return 4 " ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
dayhourviewvehiclepeakweekendcat
0Friday00:00Johor-Tuas3000
1Friday01:00Johor-Tuas15000
2Friday02:00Johor-Tuas17000
3Friday03:00Johor-Tuas6000
4Friday04:00Johor-Tuas11000
\n", "
" ], "text/plain": [ " day hour view vehicle peak weekend cat\n", "0 Friday 00:00 Johor-Tuas 3 0 0 0\n", "1 Friday 01:00 Johor-Tuas 15 0 0 0\n", "2 Friday 02:00 Johor-Tuas 17 0 0 0\n", "3 Friday 03:00 Johor-Tuas 6 0 0 0\n", "4 Friday 04:00 Johor-Tuas 11 0 0 0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "final_table.loc[:,'peak'] = final_table.loc[:,'hour'].apply(peak_hours)\n", "final_table.loc[:,'peak'] = final_table.loc[:,'peak'].astype('category')\n", "final_table.loc[:,'weekend'] = final_table.loc[:,'day'].apply(weekend)\n", "final_table.loc[:,'weekend'] = final_table.loc[:,'weekend'].astype('category')\n", "final_table.loc[:,'cat'] = final_table.loc[:,'vehicle'].apply(vehicle_cat)\n", "final_table.loc[:,'cat'] = final_table.loc[:,'cat'].astype('category')\n", "display(final_table.head(5))" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[450 121 64 45 20]\n" ] } ], "source": [ "print(np.bincount(np.array(final_table.loc[:,'cat'])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Machine Learning Model Testing-Determining Self-Made Category of Traffic Congestion" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "from sklearn.model_selection import cross_val_score, GridSearchCV, cross_validate, train_test_split\n", "from sklearn.metrics import accuracy_score, classification_report\n", "from sklearn.svm import SVC\n", "from sklearn.linear_model import LinearRegression\n", "from sklearn.neural_network import MLPClassifier\n", "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.preprocessing import StandardScaler, normalize\n", "from sklearn.decomposition import PCA\n", "from sklearn import tree" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Split the data and create dummy variables for each category" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
day_Fridayday_Mondayday_Saturdayday_Sundayday_Thursdayday_Tuesdayday_Wednesdayhour_00:00hour_01:00hour_02:00...hour_21:00hour_22:00hour_23:00hour_24:00view_Johor-Tuasview_Johor-Woodlandsview_Tuas-Johorview_Woodlands-Johorpeakweekend
01000000100...0000100000
11000000010...0000100000
21000000001...0000100000
31000000000...0000100000
41000000000...0000100000
..................................................................
6950000001000...0000000100
6960000001000...1000000100
6970000001000...0100000100
6980000001000...0010000100
6990000001000...0001000100
\n", "

700 rows × 38 columns

\n", "
" ], "text/plain": [ " day_Friday day_Monday day_Saturday day_Sunday day_Thursday \\\n", "0 1 0 0 0 0 \n", "1 1 0 0 0 0 \n", "2 1 0 0 0 0 \n", "3 1 0 0 0 0 \n", "4 1 0 0 0 0 \n", ".. ... ... ... ... ... \n", "695 0 0 0 0 0 \n", "696 0 0 0 0 0 \n", "697 0 0 0 0 0 \n", "698 0 0 0 0 0 \n", "699 0 0 0 0 0 \n", "\n", " day_Tuesday day_Wednesday hour_00:00 hour_01:00 hour_02:00 ... \\\n", "0 0 0 1 0 0 ... \n", "1 0 0 0 1 0 ... \n", "2 0 0 0 0 1 ... \n", "3 0 0 0 0 0 ... \n", "4 0 0 0 0 0 ... \n", ".. ... ... ... ... ... ... \n", "695 0 1 0 0 0 ... \n", "696 0 1 0 0 0 ... \n", "697 0 1 0 0 0 ... \n", "698 0 1 0 0 0 ... \n", "699 0 1 0 0 0 ... \n", "\n", " hour_21:00 hour_22:00 hour_23:00 hour_24:00 view_Johor-Tuas \\\n", "0 0 0 0 0 1 \n", "1 0 0 0 0 1 \n", "2 0 0 0 0 1 \n", "3 0 0 0 0 1 \n", "4 0 0 0 0 1 \n", ".. ... ... ... ... ... \n", "695 0 0 0 0 0 \n", "696 1 0 0 0 0 \n", "697 0 1 0 0 0 \n", "698 0 0 1 0 0 \n", "699 0 0 0 1 0 \n", "\n", " view_Johor-Woodlands view_Tuas-Johor view_Woodlands-Johor peak \\\n", "0 0 0 0 0 \n", "1 0 0 0 0 \n", "2 0 0 0 0 \n", "3 0 0 0 0 \n", "4 0 0 0 0 \n", ".. ... ... ... ... \n", "695 0 0 1 0 \n", "696 0 0 1 0 \n", "697 0 0 1 0 \n", "698 0 0 1 0 \n", "699 0 0 1 0 \n", "\n", " weekend \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", ".. ... \n", "695 0 \n", "696 0 \n", "697 0 \n", "698 0 \n", "699 0 \n", "\n", "[700 rows x 38 columns]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "X = final_table.loc[:,['day', 'hour','view']]\n", "Y = final_table.loc[:,'cat']\n", "\n", "X = pd.get_dummies(X)\n", "X.loc[:,['peak', 'weekend']] = final_table.loc[:,['peak', 'weekend']]\n", "display(X)\n", "\n", "x_train, x_test, y_train, y_test = train_test_split(X, Y, train_size=0.7,\n", " test_size=0.3,\n", " shuffle=True, random_state=13)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.6666666666666666\n", "[132 46 17 10 5]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "#Trial Decision tree\n", "clf = tree.DecisionTreeClassifier()\n", "clf = clf.fit(x_train, y_train)\n", "y_pred = clf.predict(x_test)\n", "\n", "print(accuracy_score(y_test, y_pred))\n", "print(np.bincount(y_pred))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n", "0.6857142857142857\n", "{'max_depth': 16, 'n_estimators': 8}\n", "0.6932253313696612\n", "[160 29 12 6 3]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "#Trial RandomForest\n", "rf_clf = RandomForestClassifier(random_state=13).fit(x_train, y_train)\n", "y_predict_train = rf_clf.predict(x_train)\n", "y_predict_test = rf_clf.predict(x_test)\n", "print(accuracy_score(y_train, y_predict_train))\n", "print(accuracy_score(y_test, y_predict_test))\n", "param_grid = {'n_estimators':[2,4,6,8,10], 'max_depth':[2,8,16,24]}\n", "gscv_rfc = GridSearchCV(rf_clf, param_grid).fit(x_train, y_train)\n", "print(gscv_rfc.best_params_)\n", "print(gscv_rfc.best_score_)\n", "\n", "print(np.bincount(y_predict_test))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.9447852760736196\n", "0.6714285714285714\n", "[159 27 14 5 5]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "rf_clf = RandomForestClassifier(random_state=13, max_depth=16, n_estimators=8).fit(x_train, y_train)\n", "y_predict_train = rf_clf.predict(x_train)\n", "y_predict_test = rf_clf.predict(x_test)\n", "print(accuracy_score(y_train, y_predict_train))\n", "print(accuracy_score(y_test, y_predict_test))\n", "\n", "print(np.bincount(y_predict_test))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.6619047619047619\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n", "/Users/roisinnichuireain/opt/anaconda3/lib/python3.9/site-packages/sklearn/neighbors/_classification.py:228: FutureWarning: Unlike other reduction functions (e.g. `skew`, `kurtosis`), the default behavior of `mode` typically preserves the axis it acts along. In SciPy 1.11.0, this behavior will change: the default value of `keepdims` will become False, the `axis` over which the statistic is taken will be eliminated, and the value None will no longer be accepted. Set `keepdims` to True or False to avoid this warning.\n", " mode, _ = stats.mode(_y[neigh_ind, k], axis=1)\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.neighbors import KNeighborsClassifier\n", "scores = []\n", "for i in range(20):\n", " neigh = KNeighborsClassifier(n_neighbors=i+1)\n", " neigh.fit(x_train, y_train)\n", " y_pred = neigh.predict(x_test)\n", " scores.append(accuracy_score(y_test, y_pred))\n", "plt.plot(scores)\n", "\n", "b = np.argmax(list(scores))\n", "neigh = KNeighborsClassifier(n_neighbors=b+1)\n", "neigh.fit(x_train, y_train)\n", "y_pred = neigh.predict(x_test)\n", "print(accuracy_score(y_test, y_pred))" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.6666666666666666\n", "[143 31 22 12 2]\n", "[133 35 19 15 8]\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.model_selection import cross_val_score\n", "from sklearn.ensemble import AdaBoostClassifier\n", "\n", "scores = []\n", "for i in range(50):\n", " clf = AdaBoostClassifier(n_estimators=i+1)\n", " clf.fit(x_train, y_train)\n", " y_pred = clf.predict(x_test)\n", " scores.append(accuracy_score(y_test, y_pred))\n", "plt.plot(scores)\n", "\n", "b = np.argmax(list(scores))\n", "clf = AdaBoostClassifier(n_estimators=b+1)\n", "clf.fit(x_train, y_train)\n", "y_pred = clf.predict(x_test)\n", "print(accuracy_score(y_test, y_pred))\n", "print(np.bincount(y_pred))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.7428571428571429\n", "[140 34 24 12]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "from sklearn.neural_network import MLPClassifier\n", "clf = MLPClassifier(solver='lbfgs', alpha=0.65, hidden_layer_sizes=(4,3), random_state=2, max_iter=3000)\n", "clf.fit(x_train, y_train)\n", "y_pred = clf.predict(x_test)\n", "print(accuracy_score(y_test, y_pred))\n", "print(np.bincount(y_pred))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "#parameters = {\"solver\":['lbfgs', 'adam', 'sgd'],\n", " #'alpha':[0.005, 0.05, 0.5,1],\n", " #'hidden_layer_sizes':[(4,3), (5,3), (6,3)]}\n", "#grid = GridSearchCV(clf, parameters).fit(x_train, y_train)\n", "#print(grid.best_params_)\n", "#print(grid.best_score_)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.7333333333333333\n", "[134 44 22 7 3]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "clf = MLPClassifier(solver='lbfgs', alpha=3, hidden_layer_sizes=(5,4), random_state=2, max_iter=3000)\n", "clf.fit(x_train, y_train)\n", "y_pred = clf.predict(x_test)\n", "print(accuracy_score(y_test, y_pred))\n", "print(np.bincount(y_pred))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.6523809523809524\n", "[158 28 12 3 9]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "from sklearn.ensemble import GradientBoostingClassifier\n", "GBC_clf = GradientBoostingClassifier(n_estimators=100, learning_rate=1.0, \n", " max_depth=1, random_state=1)\n", "GBC_clf.fit(x_train, y_train)\n", "y_pred = GBC_clf.predict(x_test)\n", "print(accuracy_score(y_test, y_pred))\n", "print(np.bincount(y_pred))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'learning_rate': 0.5, 'max_depth': 1, 'n_estimators': 100}\n", "0.7179465600673259\n" ] } ], "source": [ "parameters = {\"n_estimators\":[100, 200, 300],\n", " 'learning_rate':[0.005, 0.05, 0.5,1],\n", " 'max_depth':[1,2,3]}\n", "grid = GridSearchCV(GBC_clf, parameters).fit(x_train, y_train)\n", "print(grid.best_params_)\n", "print(grid.best_score_)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.7047619047619048\n", "[148 32 14 7 9]\n", "[133 35 19 15 8]\n" ] } ], "source": [ "GBC_clf = GradientBoostingClassifier(n_estimators=100, learning_rate=0.5, \n", " max_depth=1, random_state=2)\n", "GBC_clf.fit(x_train, y_train)\n", "y_pred = GBC_clf.predict(x_test)\n", "print(accuracy_score(y_test, y_pred))\n", "print(np.bincount(y_pred))\n", "print(np.bincount(y_test))" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Thursday\n" ] } ], "source": [ "def convert_date(date):\n", " return datetime.strptime(date, \"%Y-%m-%d\").strftime('%A') \n", "print(convert_date(\"2013-04-11\")) " ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2]\n" ] } ], "source": [ "h = '17:00'\n", "v = 'Woodlands-Johor'\n", "\n", "def create_row(date_d, hour, view):\n", " if date_d is None:\n", " date_d = \"2023-04-11\"\n", " if hour is None:\n", " hour = \"09:00\"\n", " if view is None:\n", " view = \"Johor-Tuas\"\n", " \n", " features = x_train.columns\n", " d_dict = {}\n", " day = datetime.strptime(date_d, \"%Y-%m-%d\").strftime('%A')\n", " hour = str(hour)\n", " view = str(view)\n", " col_day = \"day_\" + day\n", " col_hour = 'hour_'+ hour\n", " col_view = 'view_'+view\n", " \n", " for i in features:\n", " if i == col_day or i == col_hour or i == col_view:\n", " d_dict[i] = [1]\n", " else:\n", " d_dict[i] = [0]\n", " end = ['Saturday', 'Sunday']\n", " peak = ['07:00', \"08:00\", '09:00', \"17:00\", \"18:00\", \"19:00\"]\n", " \n", " if day in end:\n", " d_dict['weekend'] = 1\n", " if hour in peak:\n", " d_dict['peak'] = 1 \n", " result = pd.DataFrame.from_dict(d_dict, orient='columns')\n", " for i in features:\n", " result[i] = result[i].astype('category')\n", " return result\n", " \n", "print(clf.predict(create_row(\"2013-04-15\", h, v))) " ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]\n" ] } ], "source": [ "print(clf.predict(create_row(\"2013-04-17\", None, None))) " ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "figs = []\n", "\n", "for i in range(5):\n", " midway = [15, 40, 70, 110, 150]\n", " cat = ['No Traffic', 'Minimal Traffic', 'Mild Traffic', 'Moderate Traffic', 'Peak Traffic']\n", " \n", " figure = go.Figure(go.Indicator(\n", " mode = \"gauge\",\n", " value = midway[i],\n", " domain = {'x': [0, 1], 'y': [0, 1]},\n", " title = {'text': cat[i], 'font': {'size': 24}},\n", " gauge = {\n", " 'axis': {'range': [None, 156], 'tickwidth': 1, 'tickcolor': \"darkblue\"},\n", " 'bar': {'color': \"blue\"},\n", " 'bgcolor': \"white\",\n", " 'borderwidth': 2,\n", " 'bordercolor': \"gray\",\n", " 'steps': [\n", " {'range': [0, 19], 'color': 'darkgreen'},\n", " {'range': [20, 49], 'color': 'green'},\n", " {'range': [50, 79], 'color': 'yellow'},\n", " {'range': [80, 119], 'color': 'orange'},\n", " {'range': [120, 160], 'color': 'red'}],\n", " 'threshold': {\n", " 'line': {'color': \"red\", 'width': 4},\n", " 'thickness': 0.75,\n", " 'value': 490}}))\n", "\n", " figure.update_layout(paper_bgcolor = \"lavender\", font = {'color': \"darkblue\", 'family': \"Arial\"})\n", "\n", " figs.append(figure)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "# x = list of [model, date, hour, view]\n", "def predicted_figure(x):\n", " \n", " result = create_row(x[1], x[2], x[3])\n", " pred_val = clf.predict(result)[0]\n", " \n", " return figs[pred_val]\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "domain": { "x": [ 0, 1 ], "y": [ 0, 1 ] }, "gauge": { "axis": { "range": [ null, 156 ], "tickcolor": "darkblue", "tickwidth": 1 }, "bar": { "color": "blue" }, "bgcolor": "white", "bordercolor": "gray", "borderwidth": 2, "steps": [ { "color": "darkgreen", "range": [ 0, 19 ] }, { "color": "green", "range": [ 20, 49 ] }, { "color": "yellow", "range": [ 50, 79 ] }, { "color": "orange", "range": [ 80, 119 ] }, { "color": "red", "range": [ 120, 160 ] } ], "threshold": { "line": { "color": "red", "width": 4 }, "thickness": 0.75, "value": 490 } }, "mode": "gauge", "title": { "font": { "size": 24 }, "text": "Minimal Traffic" }, "type": "indicator", "value": 40 } ], "layout": { "font": { "color": "darkblue", "family": "Arial" }, "paper_bgcolor": "lavender", "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } } } }, "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "b = [clf, \"2023-04-27\", \"09:00\", \"Johor-Tuas\"]\n", "predicted_figure(b)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "from datetime import date\n", "t = str(date.today()).split('-')\n", "today = []\n", "\n", "for i in t:\n", " if t[0] =='0':\n", " today.append(int(t[1:]))\n", " else:\n", " today.append(int(i))" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "starter_variables = [clf, str(date.today()), \"07:00\", \"Tuas-Johor\"]\n", "fig = predicted_figure(starter_variables)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dash is running on http://127.0.0.1:8050/\n", "\n" ] }, { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "app = JupyterDash(__name__)\n", "\n", "app.title = 'CSE6242 Dashboard'\n", "app.layout = html.Div([\n", " html.Div([\n", " dcc.DatePickerSingle(\n", " id='my_date_picker_single',\n", " min_date_allowed=date(2023, 4, 11),\n", " max_date_allowed=date(2024, 4, 11),\n", " initial_visible_month=date(today[0],today[1], today[2]),\n", " date=date(today[0],today[1], today[2])\n", " ),\n", " html.Div(id='output-container-date-picker-single')],\n", " style={'width':'20%','height':'0px', 'padding-left':'2%',\n", " 'display':'inline-block'}),\n", " html.Div([dcc.Dropdown(id='hours_dropdown_id',\n", " options=['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', \n", " '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00','19:00',\n", " '20:00', '21:00', '22:00', '23:00'],\n", " value='07:00', clearable=False),html.Label(\"Estimated Leave Time\")],\n", " style={'width':'20%','height':'60px', 'padding-left':'2%',\n", " 'display':'inline-block'}),\n", " html.Div([dcc.Dropdown(id='direction_id',\n", " options=['Johor-Tuas','Johor-Woodlands',\n", " 'Tuas-Johor', 'Woodlands-Johor'],\n", " value=\"Tuas-Johor\", clearable=False),html.Label(\"Direction\")],\n", " style={'width':'20%','height':'60px', 'padding-left':'2%',\n", " 'display':'inline-block'}),\n", " html.Div(dcc.Graph(id='final_output', figure=fig))])\n", "\n", "\n", "@app.callback(Output('output-container-date-picker-single', 'children'),\n", " Input('my_date_picker_single', 'date'))\n", "def update_output(date_value):\n", " string_prefix = 'Travel Day: '\n", " if date_value is not None:\n", " date_object = date.fromisoformat(date_value)\n", " date_string = convert_date(date_value)\n", " return string_prefix + date_string\n", " \n", "@app.callback(Output('final_output', \"figure\"),\n", " Input('my_date_picker_single', 'date'),\n", " Input('hours_dropdown_id', 'value'),\n", " Input('direction_id', 'value'))\n", "def update_final_output_hour(my_date_picker_single, hours_dropdown_id, direction_id):\n", " starter_variables[1] = str(my_date_picker_single)\n", " starter_variables[2] = str(hours_dropdown_id)\n", " starter_variables[3] = str(direction_id)\n", " fig = predicted_figure(starter_variables)\n", " return fig\n", "\n", "#@app.callback(Output('bar_graph_output', 'figure'),\n", " #Input('my_date_picker_single', 'date'))\n", "#def update_bar_graph(my_date_picker_single):\n", " #fig_sub = make_subplots(rows=2, cols=2, shared_yaxes=True,\n", " #subplot_titles=('Johor-Tuas','Johor-Woodlands',\n", " #'Tuas-Johor', 'Woodlands-Johor'))\n", " #day = str(my_date_picker_single)\n", " #f = final_table[final_table['day']== day]\n", " #f1 = f[f['view']=='Johor-Tuas']\n", " #f2 = f[f['view']=='Johor-Woodlands']\n", " #f3 = f[f['view']=='Tuas-Johor']\n", " #f4 = f[f['view']=='Woodlands-Johor']\n", " \n", " #fig_sub.add_trace(go.Bar(f1, x='hour', y='vehicle', color='hour'),\n", " #row=1, col=1)\n", " #fig_sub.add_trace(px.bar(f2, x='hour', y='vehicle', color='hour'),\n", " #row=1, col=2)\n", " #fig_sub.add_trace(px.bar(f3, x='hour', y='vehicle', color='hour'),\n", " #row=2, col=1)\n", " #fig_sub.add_trace(px.bar(f4, x='hour', y='vehicle', color='hour'),\n", " #row=2, col=2)\n", " #fig_sub.show()\n", " \n", " \n", "app.run_server(mode='inline')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12" } }, "nbformat": 4, "nbformat_minor": 2 }