Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -17,7 +17,7 @@ st.set_page_config(page_title="Nuisance Complaints Dashboard", layout="wide")
|
|
| 17 |
st.title("Nuisance Complaints Analysis Dashboard")
|
| 18 |
st.markdown("""
|
| 19 |
* By Ruchita Alate (ralate2@illinois.edu)
|
| 20 |
-
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.
|
| 21 |
""")
|
| 22 |
|
| 23 |
# Loading and cleaning data
|
|
@@ -517,102 +517,102 @@ elif viz_type == "Complaints by Housing Block and Type":
|
|
| 517 |
# """)
|
| 518 |
# In the above code , We incorporated all of the professor's suggestions and refined the chart to make it more useful for analysis while ensuring good aesthetics. Given that the data from block 3400 onwards is very sparse, we decided to exclude these records. This adjustment helped focus the visualization on the more relevant data, providing clearer insights and improving its overall effectiveness for analysis.
|
| 519 |
|
| 520 |
-
if viz_type == "Complaints by Housing Block and Type (Incorporating Suggestions Based on Professor's Feedback)":
|
| 521 |
-
|
| 522 |
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
|
| 541 |
-
|
| 542 |
-
|
| 543 |
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
-
|
| 554 |
|
| 555 |
-
|
| 556 |
-
|
| 557 |
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
|
| 562 |
-
|
| 563 |
-
|
| 564 |
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
# Adding percentage labels to the plot
|
| 580 |
-
for idx, block in enumerate(complaint_pivot.index):
|
| 581 |
-
cumulative_height = 0
|
| 582 |
-
for i, complaint_type in enumerate(complaint_pivot.columns):
|
| 583 |
-
count = complaint_pivot.iloc[idx, i]
|
| 584 |
-
percent = percentages.iloc[idx, i]
|
| 585 |
-
if count > 0:
|
| 586 |
-
# Compute the position for the percentage label
|
| 587 |
-
x_pos = idx - 0.4 + 0.8 / 2 # Adjusting the position of the label
|
| 588 |
-
y_pos = cumulative_height + count / 2
|
| 589 |
-
ax.text(
|
| 590 |
-
x_pos, y_pos, f"{percent:.1f}%",
|
| 591 |
-
ha='center', va='center',
|
| 592 |
-
fontsize=10, color='black',
|
| 593 |
-
bbox=dict(facecolor='white', alpha=0.7, edgecolor='none')
|
| 594 |
-
)
|
| 595 |
-
cumulative_height += count
|
| 596 |
-
|
| 597 |
-
# Setting labels and title
|
| 598 |
-
ax.set_xlabel('Housing Block')
|
| 599 |
-
ax.set_ylabel('Number of Complaints')
|
| 600 |
-
ax.set_title('Complaints by Housing Block and Type')
|
| 601 |
-
|
| 602 |
-
# Display the plot in Streamlit
|
| 603 |
-
st.pyplot(fig)
|
| 604 |
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 609 |
|
| 610 |
-
|
| 611 |
-
|
| 612 |
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
| 616 |
|
| 617 |
|
| 618 |
|
|
|
|
| 17 |
st.title("Nuisance Complaints Analysis Dashboard")
|
| 18 |
st.markdown("""
|
| 19 |
* By Ruchita Alate (ralate2@illinois.edu)
|
| 20 |
+
* 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.
|
| 21 |
""")
|
| 22 |
|
| 23 |
# Loading and cleaning data
|
|
|
|
| 517 |
# """)
|
| 518 |
# In the above code , We incorporated all of the professor's suggestions and refined the chart to make it more useful for analysis while ensuring good aesthetics. Given that the data from block 3400 onwards is very sparse, we decided to exclude these records. This adjustment helped focus the visualization on the more relevant data, providing clearer insights and improving its overall effectiveness for analysis.
|
| 519 |
|
| 520 |
+
# if viz_type == "Complaints by Housing Block and Type (Incorporating Suggestions Based on Professor's Feedback)":
|
| 521 |
+
# st.subheader("Complaints by Housing Block and Type - Incorporating Suggestions Based on Professor's Feedback")
|
| 522 |
|
| 523 |
+
# # Filtering the data based on the selected year and housing block
|
| 524 |
+
# filtered_data_time = data # Use filtered_data if date range is not needed
|
| 525 |
+
# if selected_year != 'All Time':
|
| 526 |
+
# filtered_data_time = filtered_data_time[filtered_data_time['Year Reported'] == selected_year]
|
| 527 |
|
| 528 |
+
# # Further filtering by Housing Block (if applicable)
|
| 529 |
+
# if selected_block != 'All Blocks':
|
| 530 |
+
# filtered_data_time = filtered_data_time[filtered_data_time['Housing Block'] == selected_block]
|
| 531 |
|
| 532 |
+
# # Pivoting the data based on the filtered data
|
| 533 |
+
# complaint_pivot = filtered_data_time.pivot_table(
|
| 534 |
+
# index='Housing Block',
|
| 535 |
+
# columns='Type of Complaint',
|
| 536 |
+
# values='Disposition',
|
| 537 |
+
# aggfunc='count',
|
| 538 |
+
# fill_value=0
|
| 539 |
+
# )
|
| 540 |
|
| 541 |
+
# # Ensuring the pivoted data is numeric for plotting
|
| 542 |
+
# complaint_pivot = complaint_pivot.astype(float)
|
| 543 |
|
| 544 |
+
# # Desired order for the housing blocks
|
| 545 |
+
# desired_order = [
|
| 546 |
+
# '1 block', '100 block', '200 block', '300 block', '400 block', '500 block',
|
| 547 |
+
# '600 block', '700 block', '800 block', '900 block', '1000 block', '1100 block',
|
| 548 |
+
# '1200 block', '1300 block', '1400 block', '1500 block', '1600 block',
|
| 549 |
+
# '1700 block', '1800 block', '1900 block', '2000 block', '2100 block',
|
| 550 |
+
# '2200 block', '2300 block', '2400 block', '2500 block', '2600 block',
|
| 551 |
+
# '2700 block', '2800 block', '2900 block', '3000 block', '3100 block',
|
| 552 |
+
# '3200 block', '3300 block'
|
| 553 |
+
# ]
|
| 554 |
|
| 555 |
+
# # Reordering the index of the pivot table according to the desired order
|
| 556 |
+
# complaint_pivot = complaint_pivot.reindex(desired_order)
|
| 557 |
|
| 558 |
+
# # If a single block is selected, filter for only that block
|
| 559 |
+
# if selected_block != 'All Blocks':
|
| 560 |
+
# complaint_pivot = complaint_pivot.loc[[selected_block]]
|
| 561 |
|
| 562 |
+
# # Calculating percentages for each complaint type per housing block
|
| 563 |
+
# percentages = complaint_pivot.div(complaint_pivot.sum(axis=1), axis=0) * 100
|
| 564 |
|
| 565 |
+
# # Plotting the data
|
| 566 |
+
# fig, ax = plt.subplots(figsize=(10, 6))
|
| 567 |
+
# complaint_pivot.plot(kind='bar', stacked=True, colormap='inferno', ax=ax)
|
| 568 |
|
| 569 |
+
# # Adjusting the x-axis ticks
|
| 570 |
+
# if selected_block != 'All Blocks':
|
| 571 |
+
# ax.set_xticks([0]) # Only one label
|
| 572 |
+
# ax.set_xticklabels([selected_block], rotation=0)
|
| 573 |
+
# else:
|
| 574 |
+
# # Show every nth label to avoid overcrowding
|
| 575 |
+
# tick_spacing = max(1, len(complaint_pivot) // 10) # Adjust based on the number of blocks
|
| 576 |
+
# ax.set_xticks(range(0, len(complaint_pivot.index), tick_spacing))
|
| 577 |
+
# ax.set_xticklabels(complaint_pivot.index[::tick_spacing], rotation=45, ha='right')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 578 |
|
| 579 |
+
# # Adding percentage labels to the plot
|
| 580 |
+
# for idx, block in enumerate(complaint_pivot.index):
|
| 581 |
+
# cumulative_height = 0
|
| 582 |
+
# for i, complaint_type in enumerate(complaint_pivot.columns):
|
| 583 |
+
# count = complaint_pivot.iloc[idx, i]
|
| 584 |
+
# percent = percentages.iloc[idx, i]
|
| 585 |
+
# if count > 0:
|
| 586 |
+
# # Compute the position for the percentage label
|
| 587 |
+
# x_pos = idx - 0.4 + 0.8 / 2 # Adjusting the position of the label
|
| 588 |
+
# y_pos = cumulative_height + count / 2
|
| 589 |
+
# ax.text(
|
| 590 |
+
# x_pos, y_pos, f"{percent:.1f}%",
|
| 591 |
+
# ha='center', va='center',
|
| 592 |
+
# fontsize=10, color='black',
|
| 593 |
+
# bbox=dict(facecolor='white', alpha=0.7, edgecolor='none')
|
| 594 |
+
# )
|
| 595 |
+
# cumulative_height += count
|
| 596 |
+
|
| 597 |
+
# # Setting labels and title
|
| 598 |
+
# ax.set_xlabel('Housing Block')
|
| 599 |
+
# ax.set_ylabel('Number of Complaints')
|
| 600 |
+
# ax.set_title('Complaints by Housing Block and Type')
|
| 601 |
+
|
| 602 |
+
# # Display the plot in Streamlit
|
| 603 |
+
# st.pyplot(fig)
|
| 604 |
+
|
| 605 |
+
# # Writeup
|
| 606 |
+
# st.write("""
|
| 607 |
+
# **What this visualization shows:**
|
| 608 |
+
# This bar chart displays the distribution of complaints by Housing Block and Complaint Type. The data is stacked to show the percentage of complaints per block, categorized by type. This allows for a quick comparison of the most common complaint types across different housing blocks. While the percentages may be challenging to read when data for all blocks is displayed, they become more valuable and easier to interpret when a single block is selected. Selecting a specific block allows for clearer insights into the proportion of each complaint type within that block, providing more actionable information.
|
| 609 |
|
| 610 |
+
# **Why it's interesting:**
|
| 611 |
+
# 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. Given that the data from block 3400 onwards is very sparse, we decided to exclude these records. This adjustment helped focus the visualization on the more relevant data, providing clearer insights and improving its overall effectiveness for analysis.
|
| 612 |
|
| 613 |
+
# **Color Scheme:**
|
| 614 |
+
# 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.
|
| 615 |
+
# """)
|
| 616 |
|
| 617 |
|
| 618 |
|