diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..9fa9d55 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: voila --port=$PORT --no-browser --enable_nbextensions=True sf_crime.ipynb diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e761c32 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +voila +folium +numpy +pandas +ipywidgets +ipykernel +matplotlib \ No newline at end of file diff --git a/sf_crime.ipynb b/sf_crime.ipynb new file mode 100644 index 0000000..cc5d90a --- /dev/null +++ b/sf_crime.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Simple Dashboard of San Fransisco Crime Dataset with Voila" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import folium" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.11.0\n" + ] + } + ], + "source": [ + "print(folium.__version__)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('SF_crimes.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import ipywidgets as widgets\n", + "\n", + "style = {'description_width': 'initial'}\n", + "\n", + "limit_case = widgets.IntSlider(\n", + " value=1000,\n", + " min=100,\n", + " max=5000,\n", + " step=1,\n", + " description='Max Number of Case:',\n", + " disabled=False,\n", + " style=style)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "unique_district = df.PdDistrict.unique()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "unique_cat = df.Category.unique()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from ipywidgets import Layout\n", + "\n", + "\n", + "\n", + "district = widgets.SelectMultiple(\n", + " options = unique_district.tolist(),\n", + " value = ['BAYVIEW', 'NORTHERN'],\n", + " #rows=10,\n", + " description='District',\n", + " disabled=False,\n", + " layout = Layout(width='50%', height='80px')\n", + ")\n", + "\n", + "category = widgets.SelectMultiple(\n", + " options = unique_cat.tolist(),\n", + " value = ['VANDALISM', 'ASSAULT', 'ROBBERY'],\n", + " #rows=10,\n", + " description='Criminal Case',\n", + " disabled=False,\n", + " style=style,\n", + " layout = Layout(width='50%', height='80px')\n", + ")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "from folium import plugins\n", + "\n", + "def update_map(district, category, limit):\n", + " \n", + " df = pd.read_csv('SF_crimes.csv')\n", + " df = df.iloc[0:limit, :]\n", + " \n", + " latitude = 37.77\n", + " longitude = -122.42\n", + " \n", + " df_dist = df.loc[df['PdDistrict'].isin(np.array(district))]\n", + " df_category = df_dist.loc[df_dist['Category'].isin(np.array(category))]\n", + " \n", + " cat_unique = df_category['Category'].value_counts()\n", + " cat_unique = cat_unique.reset_index()\n", + " \n", + " dist_unique = df_category['PdDistrict'].value_counts()\n", + " dist_unique = dist_unique.reset_index()\n", + " \n", + " fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20,10))\n", + "\n", + " # create map and display it\n", + " sanfran_map = folium.Map(location=[latitude, longitude], zoom_start=12)\n", + "\n", + " \n", + " incidents = plugins.MarkerCluster().add_to(sanfran_map)\n", + "\n", + "# loop through the dataframe and add each data point to the mark cluster\n", + " for lat, lng, label, in zip(df_category.Y, df_category.X, df_category.Category):\n", + " folium.Marker(\n", + " location=[lat, lng],\n", + " icon=None,\n", + " popup=label,\n", + " ).add_to(incidents)\n", + "# show map\n", + " display(sanfran_map)\n", + " \n", + " ax1.bar(cat_unique['index'], cat_unique['Category'])\n", + " ax1.set_title('Amount of Criminal Case Based on Category')\n", + " ax2.bar(dist_unique['index'], dist_unique['PdDistrict'])\n", + " ax2.set_title('Amount of Criminal Case in Selected District')\n", + " \n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c185e97d8e6e44bd99be6e236eee426a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(SelectMultiple(description='District', index=(0, 1), layout=Layout(height='80px', width=…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "widgets.interactive(update_map, district = district, category = category, limit=limit_case)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}