diff options
Diffstat (limited to 'app.py')
-rw-r--r-- | app.py | 95 |
1 files changed, 69 insertions, 26 deletions
@@ -1,7 +1,9 @@ from dash import Dash, html, dcc, callback, Output, Input, dash_table import plotly.express as px import pandas as pd +import numpy as np import sqlite3 +from datetime import datetime, date # Connect to database and query all incidents connection = sqlite3.connect("./raw_data/ingress.db") @@ -9,44 +11,51 @@ cursor = connection.cursor() query = "SELECT * FROM incidents;" df = pd.read_sql_query(query, connection).sort_values(by="description") -# Create custom YEAR column to use in dropdown -df['year'] = df['date'].str[-4:] +# Replace empty cells with NaN +df = df.replace(r'^\s*$', np.nan, regex=True) + +# Convert date column to datetime +# TODO: Create a combined datetime column in the db to load/convert here +df["date"] = pd.to_datetime(df["date"]) # Configure HTML layout app = Dash(__name__) app.layout = html.Div(children = [ - html.H1(children="Omaha Police Incidents", style={"textAlign":"center"}), + html.H1(children="Omaha Crime Mapping & Analysis", style={"textAlign":"center"}), html.Div([ - html.H2(children="Totals per Category and Year", style={"textAlign":"center"}), - dcc.Dropdown(df.sort_values("description").description.unique(), "INJURY", id="dropdown"), - dcc.Dropdown(df.sort_values("year").year.unique(), "2023", id="year-dropdown"), - html.Hr(), - dash_table.DataTable(data=df.to_dict("records"), page_size=5, id="table"), - html.H2(children="Map of Incidents per Category and Year", style={"textAlign":"center"}), - dcc.Graph(id="map-graph") + html.Div(className="flex", + children = [ + html.P("Crime:"), + dcc.Dropdown(df.sort_values("description").description.unique(), "INJURY", id="dropdown"), + ] + ), + html.Div(className="flex", + children = [ + html.P("Date Range:"), + dcc.DatePickerRange( + id='date-picker-range', + min_date_allowed=date(2015, 1, 1), + max_date_allowed=date(2023, 12, 31), + start_date=date(2015, 1, 1), + end_date=date(2023,12,31) + ), + ] + ), + dcc.Graph(id="map-graph"), + dcc.Graph(id="line-graph"), + dash_table.DataTable(data=df.to_dict("records"), page_size=5, id="table") ]) ]) -# Create table -@callback( - Output("table", "data"), - Input("dropdown", "value"), - Input("year-dropdown", "value") -) -def update_table(description, year): - dff = df[df.year == year] - dff = dff.reset_index() - dff = dff[dff.description == description] - return dff.to_dict("records") - # Create map @callback( Output("map-graph", "figure"), Input("dropdown", "value"), - Input("year-dropdown", "value") + Input('date-picker-range', 'start_date'), + Input('date-picker-range', 'end_date') ) -def update_map(description, year): - dff = df[df.year == year] +def update_map(description, start_date, end_date): + dff = df[(df['date'] > start_date) & (df['date'] < end_date)] dff = dff.reset_index() dff = dff[dff.description == description] @@ -54,7 +63,6 @@ def update_map(description, year): dff, lat="lat", lon="lon", - color="description", hover_name="description", hover_data=["date", "time"], title="Incident Count by Coordinates", @@ -69,5 +77,40 @@ def update_map(description, year): return fig +# Create line graph +@callback( + Output("line-graph", "figure"), + Input("dropdown", "value"), + Input('date-picker-range', 'start_date'), + Input('date-picker-range', 'end_date') +) +def update_line(description, start_date, end_date): + dff = df[(df['date'] > start_date) & (df['date'] < end_date)] + dff = dff.reset_index() + dff = dff[dff.description == description] + dff = dff.groupby(by="date").count() + dff = dff.reset_index() + + fig = px.line( + dff, + x="date", + y="description", + ) + + return fig + +# Create table +@callback( + Output("table", "data"), + Input("dropdown", "value"), + Input('date-picker-range', 'start_date'), + Input('date-picker-range', 'end_date') +) +def update_table(description, start_date, end_date): + dff = df[(df['date'] > start_date) & (df['date'] < end_date)] + dff = dff.reset_index() + dff = dff[dff.description == description] + return dff.to_dict("records") + if __name__ == "__main__": app.run(debug=True) |