ralate2 commited on
Commit
7d2753c
·
verified ·
1 Parent(s): 23e91fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -86
app.py CHANGED
@@ -10,7 +10,7 @@ from folium.plugins import HeatMap
10
  from streamlit_folium import st_folium
11
  import plotly.express as px
12
 
13
- # Set page config
14
  st.set_page_config(page_title="Nuisance Complaints Dashboard", layout="wide")
15
 
16
  # Title and introduction
@@ -26,7 +26,7 @@ st.markdown("""
26
  This dashboard analyzes nuisance complaints data from the City of Urbana. The visualizations aim to explore complaint trends, resolution efficiency, and geographic patterns to provide actionable insights for urban planning and management.
27
  """)
28
 
29
- # Load and clean data
30
  @st.cache_data
31
  def load_and_clean_data():
32
  data = pd.read_csv('Nuisance_Complaints_20241130.csv')
@@ -35,7 +35,7 @@ def load_and_clean_data():
35
  data['Date Notice Mailed or Given'] = pd.to_datetime(data['Date Notice Mailed or Given'])
36
  data['File Close Date'] = pd.to_datetime(data['File Close Date'], errors='coerce')
37
 
38
- # Fill missing dates
39
  median_delay = (data['Date Notice Mailed or Given'] - data['Date Reported']).dt.days.median()
40
  data.loc[data['Date Notice Mailed or Given'].isna(), 'Date Notice Mailed or Given'] = \
41
  data.loc[data['Date Notice Mailed or Given'].isna(), 'Date Reported'] + pd.Timedelta(days=median_delay)
@@ -64,79 +64,20 @@ def load_and_clean_data():
64
  data['Month Reported'] = data['Date Reported'].dt.month
65
  return data
66
 
67
- # Load the data
68
  data = load_and_clean_data()
69
 
70
- # # Sidebar for controls
71
- # st.sidebar.header("Dashboard Controls")
72
-
73
- # # First, define the visualization type (viz_type) selection
74
- # viz_type = st.sidebar.selectbox("Select Visualization", [
75
- # "Complaint Types", "Geographic Distribution", "Complaints by Disposition", "Submission Methods","Monthly Trends by Complaint Type",
76
- # "Complaints Over Time", "Complaints by Housing Block and Type"
77
- # ])
78
-
79
- # # Remove the year selection when certain visualizations are selected
80
- # if viz_type not in ["Complaints Over Time", "Complaints by Housing Block and Type"]:
81
- # year_options = ['All Time'] + sorted(data['Year Reported'].unique().tolist())
82
- # selected_year = st.sidebar.selectbox("Select Year", options=year_options)
83
- # else:
84
- # selected_year = 'All Time' # Default to 'All Time' if visualization doesn't require year
85
-
86
- # # Date Range Selector for Complaints Over Time (only show when Complaints Over Time is selected)
87
- # if viz_type == "Complaints Over Time":
88
- # start_date = st.sidebar.date_input("Start Date", pd.to_datetime("2020-01-01"))
89
- # end_date = st.sidebar.date_input("End Date", pd.to_datetime("2024-12-31"))
90
-
91
- # # Allow the user to select the type of chart (Bar or Pie) for Submission Methods
92
- # if viz_type == "Submission Methods":
93
- # plot_type = st.sidebar.selectbox("Select Plot Type", options=["Bar Chart", "Pie Chart"])
94
-
95
- # # Dropdown for Housing Block (only show when Complaints by Housing Block and Type is selected)
96
- # if viz_type == "Complaints by Housing Block and Type":
97
- # block_options = ['All Blocks'] + sorted(data['Housing Block'].unique().tolist())
98
- # selected_block = st.sidebar.selectbox("Select Housing Block", options=block_options)
99
-
100
- # # Ensure selected_block is only used if defined
101
- # if viz_type == "Complaints by Housing Block and Type" and 'selected_block' not in locals():
102
- # selected_block = 'All Blocks' # Default to 'All Blocks' if no selection made
103
-
104
- # # Filter data based on selected year
105
- # if selected_year != 'All Time':
106
- # filtered_data = data[data['Year Reported'] == selected_year]
107
- # else:
108
- # filtered_data = data
109
-
110
- # # Further filter by Housing Block
111
- # if 'selected_block' in locals() and selected_block != 'All Blocks':
112
- # filtered_data = filtered_data[filtered_data['Housing Block'] == selected_block]
113
-
114
- # # Filter data based on date range (only for Complaints Over Time visualization)
115
- # if viz_type == "Complaints Over Time":
116
- # filtered_data_time = filtered_data[
117
- # (filtered_data['Date Reported'] >= pd.to_datetime(start_date)) &
118
- # (filtered_data['Date Reported'] <= pd.to_datetime(end_date))
119
- # ]
120
- # else:
121
- # filtered_data_time = filtered_data
122
-
123
- # # Filter data based on selected housing block (only for Complaints by Housing Block visualization)
124
- # if viz_type == "Complaints by Housing Block and Type" and selected_block != 'All Blocks':
125
- # filtered_data_time = filtered_data_time[filtered_data_time['Housing Block'] == selected_block]
126
-
127
- # # Header for selected year
128
- # st.header(f"Analysis for {'All Time' if selected_year == 'All Time' else selected_year}")
129
 
130
  # Sidebar for controls
131
  st.sidebar.header("Dashboard Controls")
132
 
133
- # First, define the visualization type (viz_type) selection
134
  viz_type = st.sidebar.selectbox("Select Visualization", [
135
  "Complaint Types", "Geographic Distribution", "Complaints by Disposition", "Submission Methods",
136
  "Monthly Trends by Complaint Type", "Complaints Over Time", "Complaints by Housing Block and Type"
137
  ])
138
 
139
- # Remove the year selection when certain visualizations are selected
140
  if viz_type not in ["Complaints Over Time", "Complaints by Housing Block and Type"]:
141
  year_options = ['All Time'] + sorted(data['Year Reported'].unique().tolist())
142
  selected_year = st.sidebar.selectbox("Select Year", options=year_options, key="year_select")
@@ -153,25 +94,21 @@ if viz_type == "Complaints by Housing Block and Type":
153
  block_options = ['All Blocks'] + sorted(data['Housing Block'].unique().tolist())
154
  selected_block = st.sidebar.selectbox("Select Housing Block", options=block_options, key="block_select")
155
 
156
- # # Allow the user to select the type of chart (Bar or Pie) for Submission Methods
157
- # if viz_type == "Submission Methods":
158
- # plot_type = st.sidebar.selectbox("Select Plot Type", options=["Bar Chart", "Pie Chart"], key="plot_type_select")
159
-
160
- # Ensure selected_block is only used if defined
161
  if viz_type == "Complaints by Housing Block and Type" and 'selected_block' not in locals():
162
  selected_block = 'All Blocks' # Default to 'All Blocks' if no selection made
163
 
164
- # Filter data based on selected year
165
  if selected_year != 'All Time':
166
  filtered_data = data[data['Year Reported'] == selected_year]
167
  else:
168
  filtered_data = data
169
 
170
- # Further filter by Housing Block
171
  if 'selected_block' in locals() and selected_block != 'All Blocks':
172
  filtered_data = filtered_data[filtered_data['Housing Block'] == selected_block]
173
 
174
- # Filter data based on date range (only for Complaints Over Time visualization)
175
  if viz_type == "Complaints Over Time":
176
  filtered_data_time = filtered_data[
177
  (filtered_data['Date Reported'] >= pd.to_datetime(start_date)) &
@@ -180,7 +117,7 @@ if viz_type == "Complaints Over Time":
180
  else:
181
  filtered_data_time = filtered_data
182
 
183
- # Filter data based on selected housing block (only for Complaints by Housing Block visualization)
184
  if viz_type == "Complaints by Housing Block and Type" and selected_block != 'All Blocks':
185
  filtered_data_time = filtered_data_time[filtered_data_time['Housing Block'] == selected_block]
186
 
@@ -189,7 +126,7 @@ st.header(f"Analysis for {'All Time' if selected_year == 'All Time' else selecte
189
 
190
 
191
 
192
- # Display metrics
193
  col1, col2 = st.columns(2)
194
  with col1:
195
  st.metric("Total Complaints", len(filtered_data))
@@ -339,6 +276,7 @@ elif viz_type == "Submission Methods":
339
  # **Color Scheme:**
340
  # The 'viridis' color palette highlights differences in complaint resolution status, with lighter shades indicating a higher frequency of resolved complaints.
341
  # """)
 
342
 
343
  elif viz_type == "Complaints by Disposition":
344
  st.subheader("Complaints by Disposition")
@@ -369,7 +307,6 @@ elif viz_type == "Complaints by Disposition":
369
  """)
370
 
371
 
372
-
373
  elif viz_type == "Monthly Trends by Complaint Type":
374
  st.subheader("Monthly Trends Grouped by Complaint Types")
375
  monthly_trends = filtered_data.groupby(['Month Reported', 'Type of Complaint']).size().reset_index(name='Count')
@@ -385,7 +322,7 @@ elif viz_type == "Monthly Trends by Complaint Type":
385
  This line chart visualizes the monthly trends in complaint counts, grouped by complaint type. It allows tracking changes in complaint frequencies over time and identifying patterns or spikes in specific categories.
386
 
387
  **Why it's interesting:**
388
- By visualizing these trends, you can identify whether certain complaint types are seasonal or are influenced by specific events. This information helps prioritize resources and refine strategies for complaint management.
389
 
390
  **Color Scheme:**
391
  Different complaint types are represented by distinct colors, enabling easy comparison of trends across categories.
@@ -409,6 +346,8 @@ elif viz_type == "Monthly Trends by Complaint Type":
409
  # **Color Scheme:**
410
  # The 'inferno' palette is used to emphasize the frequency of each complaint type, with darker shades representing higher frequencies.
411
  # """)
 
 
412
 
413
  elif viz_type == "Complaints Over Time":
414
  st.subheader("Complaints Over Time")
@@ -420,10 +359,15 @@ elif viz_type == "Complaints Over Time":
420
  st.pyplot(fig)
421
 
422
  st.write("""
423
- **Write-up:** This visualization displays the trend of complaints over time using a line chart.
424
- It shows the number of complaints reported for each day, making it easy to spot peaks or declines in complaints.
425
- The use of a blue color scheme highlights the flow and continuity of the data, providing a clear view of the patterns over time.
426
- """)
 
 
 
 
 
427
 
428
  elif viz_type == "Complaints by Housing Block and Type":
429
  st.subheader("Complaints by Housing Block and Type")
@@ -455,14 +399,14 @@ elif viz_type == "Complaints by Housing Block and Type":
455
 
456
  st.write("""
457
  **What this visualization shows:**
458
- This line chart shows the trend of complaints over time, displaying the number of complaints reported for each day. It helps identify patterns, peaks, and trends in the complaints data.
459
 
460
  **Why it's interesting:**
461
- By visualizing complaints over time, organizations can track the effectiveness of their responses and interventions. It also helps identify recurring spikes or declines in complaints, which could be indicative of specific events or issues.
462
 
463
- **Insight Potential:**
464
- This chart can be used to correlate with external factors, such as changes in policies, incidents, or other events that might lead to a sudden increase or decrease in complaints. The insights can inform better decision-making and improve the organization's complaint management strategy.
465
- """)
466
 
467
  # Footer
468
  st.markdown("---")
 
10
  from streamlit_folium import st_folium
11
  import plotly.express as px
12
 
13
+ # Setting page config
14
  st.set_page_config(page_title="Nuisance Complaints Dashboard", layout="wide")
15
 
16
  # Title and introduction
 
26
  This dashboard analyzes nuisance complaints data from the City of Urbana. The visualizations aim to explore complaint trends, resolution efficiency, and geographic patterns to provide actionable insights for urban planning and management.
27
  """)
28
 
29
+ # Loading and cleaning data
30
  @st.cache_data
31
  def load_and_clean_data():
32
  data = pd.read_csv('Nuisance_Complaints_20241130.csv')
 
35
  data['Date Notice Mailed or Given'] = pd.to_datetime(data['Date Notice Mailed or Given'])
36
  data['File Close Date'] = pd.to_datetime(data['File Close Date'], errors='coerce')
37
 
38
+ # Filling missing dates
39
  median_delay = (data['Date Notice Mailed or Given'] - data['Date Reported']).dt.days.median()
40
  data.loc[data['Date Notice Mailed or Given'].isna(), 'Date Notice Mailed or Given'] = \
41
  data.loc[data['Date Notice Mailed or Given'].isna(), 'Date Reported'] + pd.Timedelta(days=median_delay)
 
64
  data['Month Reported'] = data['Date Reported'].dt.month
65
  return data
66
 
67
+ # Loading the data
68
  data = load_and_clean_data()
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
  # Sidebar for controls
72
  st.sidebar.header("Dashboard Controls")
73
 
74
+ # Defining the visualization type (viz_type) selection
75
  viz_type = st.sidebar.selectbox("Select Visualization", [
76
  "Complaint Types", "Geographic Distribution", "Complaints by Disposition", "Submission Methods",
77
  "Monthly Trends by Complaint Type", "Complaints Over Time", "Complaints by Housing Block and Type"
78
  ])
79
 
80
+ # Removing the year selection when certain visualizations are selected
81
  if viz_type not in ["Complaints Over Time", "Complaints by Housing Block and Type"]:
82
  year_options = ['All Time'] + sorted(data['Year Reported'].unique().tolist())
83
  selected_year = st.sidebar.selectbox("Select Year", options=year_options, key="year_select")
 
94
  block_options = ['All Blocks'] + sorted(data['Housing Block'].unique().tolist())
95
  selected_block = st.sidebar.selectbox("Select Housing Block", options=block_options, key="block_select")
96
 
97
+ # Ensuring selected_block is only used if defined
 
 
 
 
98
  if viz_type == "Complaints by Housing Block and Type" and 'selected_block' not in locals():
99
  selected_block = 'All Blocks' # Default to 'All Blocks' if no selection made
100
 
101
+ # Filtering data based on selected year
102
  if selected_year != 'All Time':
103
  filtered_data = data[data['Year Reported'] == selected_year]
104
  else:
105
  filtered_data = data
106
 
107
+ # Further filtering by Housing Block
108
  if 'selected_block' in locals() and selected_block != 'All Blocks':
109
  filtered_data = filtered_data[filtered_data['Housing Block'] == selected_block]
110
 
111
+ # Filtering data based on date range (only for Complaints Over Time visualization)
112
  if viz_type == "Complaints Over Time":
113
  filtered_data_time = filtered_data[
114
  (filtered_data['Date Reported'] >= pd.to_datetime(start_date)) &
 
117
  else:
118
  filtered_data_time = filtered_data
119
 
120
+ # Filtering data based on selected housing block (only for Complaints by Housing Block visualization)
121
  if viz_type == "Complaints by Housing Block and Type" and selected_block != 'All Blocks':
122
  filtered_data_time = filtered_data_time[filtered_data_time['Housing Block'] == selected_block]
123
 
 
126
 
127
 
128
 
129
+ # Displaying metrics
130
  col1, col2 = st.columns(2)
131
  with col1:
132
  st.metric("Total Complaints", len(filtered_data))
 
276
  # **Color Scheme:**
277
  # The 'viridis' color palette highlights differences in complaint resolution status, with lighter shades indicating a higher frequency of resolved complaints.
278
  # """)
279
+ # We collectively decided to opt for more engaging and interactive charts instead of the above chart.
280
 
281
  elif viz_type == "Complaints by Disposition":
282
  st.subheader("Complaints by Disposition")
 
307
  """)
308
 
309
 
 
310
  elif viz_type == "Monthly Trends by Complaint Type":
311
  st.subheader("Monthly Trends Grouped by Complaint Types")
312
  monthly_trends = filtered_data.groupby(['Month Reported', 'Type of Complaint']).size().reset_index(name='Count')
 
322
  This line chart visualizes the monthly trends in complaint counts, grouped by complaint type. It allows tracking changes in complaint frequencies over time and identifying patterns or spikes in specific categories.
323
 
324
  **Why it's interesting:**
325
+ By visualizing these trends, we can identify whether certain complaint types are seasonal or are influenced by specific events. This information helps prioritize resources and refine strategies for complaint management.
326
 
327
  **Color Scheme:**
328
  Different complaint types are represented by distinct colors, enabling easy comparison of trends across categories.
 
346
  # **Color Scheme:**
347
  # The 'inferno' palette is used to emphasize the frequency of each complaint type, with darker shades representing higher frequencies.
348
  # """)
349
+ # We collectively decided to opt for more engaging and interactive charts instead of the above chart.
350
+
351
 
352
  elif viz_type == "Complaints Over Time":
353
  st.subheader("Complaints Over Time")
 
359
  st.pyplot(fig)
360
 
361
  st.write("""
362
+ **What this visualization shows:**
363
+ This visualization displays the trend of complaints over time using a line chart. It shows the number of complaints reported , making it easy to spot peaks or declines in complaints.
364
+
365
+ **Why it's interesting:**
366
+ By examining the complaints over time, users can identify patterns, such as specific days or periods with higher or lower complaint volumes. This can inform decision-making and help allocate resources more effectively during high-complaint periods.
367
+
368
+ **Color Scheme:**
369
+ The use of a purple color scheme highlights the flow and continuity of the data, providing a clear view of the patterns over time.
370
+ """)
371
 
372
  elif viz_type == "Complaints by Housing Block and Type":
373
  st.subheader("Complaints by Housing Block and Type")
 
399
 
400
  st.write("""
401
  **What this visualization shows:**
402
+ This bar chart displays the distribution of complaints by Housing Block and Complaint Type. The data is stacked to show the total number of complaints per block, categorized by type. This allows for a quick comparison of the most common complaint types across different housing blocks.
403
 
404
  **Why it's interesting:**
405
+ By analyzing the distribution of complaints by both block and type, organizations can identify specific areas where certain complaint types are more prevalent. This insight helps target interventions and allocate resources more efficiently based on the most common issues in different housing blocks.
406
 
407
+ **Color Scheme:**
408
+ The 'inferno' color palette is used to represent different complaint types, with darker shades indicating a higher frequency of complaints. The stacked bar chart makes it easy to compare the distribution of complaints by block and type.
409
+ """)
410
 
411
  # Footer
412
  st.markdown("---")