Spaces:
Sleeping
Sleeping
update tab 2
Browse files
app.py
CHANGED
@@ -3,21 +3,9 @@ import pandas as pd
|
|
3 |
import plotly.express as px
|
4 |
import altair as alt
|
5 |
import folium
|
6 |
-
from streamlit_plotly_events import plotly_events # added for part3 interactivity
|
7 |
from folium.plugins import HeatMap, MarkerCluster
|
8 |
from streamlit_folium import st_folium
|
9 |
|
10 |
-
# To fix the color scheme in crash stats plot (asked ChatGPT for appropriate colors)
|
11 |
-
severity_colors = {
|
12 |
-
"No Injury": "#1f77b4",
|
13 |
-
"Possible Injury": "#aec7e8",
|
14 |
-
"Non Incapacitating Injury": "#ff7f0e",
|
15 |
-
"Incapacitating Injury": "#ffbb78",
|
16 |
-
"Suspected Minor Injury": "#2ca02c",
|
17 |
-
"Suspected Serious Injury": "#98df8a",
|
18 |
-
"Fatal": "#d62728",
|
19 |
-
}
|
20 |
-
|
21 |
@st.cache_data
|
22 |
def load_and_preprocess_data(file_path):
|
23 |
# Read the data
|
@@ -80,40 +68,22 @@ def create_severity_violation_chart(df, age_group=None):
|
|
80 |
y='count',
|
81 |
color='Severity',
|
82 |
title=f'Crash Severity Distribution by Violation Type - {age_group}',
|
83 |
-
height=600,
|
84 |
labels={'count': 'Number of Incidents', 'Violation': 'Violation Type'},
|
85 |
-
|
86 |
)
|
87 |
|
88 |
-
# fig.update_layout(
|
89 |
-
# xaxis_tickangle=-45,
|
90 |
-
# legend_title='Severity Level',
|
91 |
-
# barmode='stack'
|
92 |
-
# )
|
93 |
-
|
94 |
-
# modified the above code because x-axis labels were partially pruned
|
95 |
fig.update_layout(
|
96 |
xaxis_tickangle=-45,
|
97 |
-
|
98 |
-
|
99 |
-
x=1,
|
100 |
-
y=1,
|
101 |
-
yanchor='top',
|
102 |
-
xanchor='left',
|
103 |
-
title="Severity Level"
|
104 |
-
),
|
105 |
-
barmode='stack',
|
106 |
-
margin=dict(t=50, b=150,r=0), # Increase bottom margin to avoid pruning
|
107 |
-
xaxis=dict(automargin=True)
|
108 |
)
|
109 |
|
110 |
-
|
111 |
-
return fig, violations
|
112 |
|
113 |
def get_top_violations(df, age_group):
|
114 |
# Calculate total incidents for the age group
|
115 |
if age_group == 'All Ages':
|
116 |
-
total_incidents = len(df)
|
117 |
# Get violations for all ages
|
118 |
violations = pd.concat([
|
119 |
df['Violation1_Drv1'].value_counts(),
|
@@ -145,70 +115,19 @@ def get_top_violations(df, age_group):
|
|
145 |
|
146 |
return violations_df.head()
|
147 |
|
148 |
-
|
149 |
-
def create_interactive_pie_chart(violations, selected_violation, selected_age):
|
150 |
-
# Filter data based on selected violation
|
151 |
-
filtered_data = violations[violations['Violation'] == selected_violation]
|
152 |
-
|
153 |
-
# Create a pie chart for severity distribution of the selected violation type
|
154 |
-
fig = px.pie(
|
155 |
-
filtered_data,
|
156 |
-
names='Severity',
|
157 |
-
values='count',
|
158 |
-
# title=f'Severity Level Distribution for Violation: {selected_violation}',
|
159 |
-
title=f'Severity Level Distribution for Violation: {selected_violation} - {selected_age}', # dynamically update pie chart's title
|
160 |
-
height=600,
|
161 |
-
color_discrete_map=severity_colors
|
162 |
-
)
|
163 |
-
|
164 |
-
return fig
|
165 |
-
|
166 |
-
def create_map_bar_chart(df, selected_year):
|
167 |
-
# Create severity count bar chart
|
168 |
-
filtered_df = df[df['Year'] == selected_year]
|
169 |
-
severity_count = filtered_df['Injuryseverity'].value_counts().reset_index()
|
170 |
-
severity_count.columns = ['Injuryseverity', 'Count']
|
171 |
-
|
172 |
-
fig = px.bar(
|
173 |
-
severity_count,
|
174 |
-
x='Injuryseverity',
|
175 |
-
y='Count',
|
176 |
-
title="Accidents by Severity",
|
177 |
-
labels={'Injuryseverity': 'Severity', 'Count': 'Number of Accidents'} # Adjust height as needed
|
178 |
-
)
|
179 |
-
fig.update_traces(marker_color='blue')
|
180 |
-
fig.update_layout(
|
181 |
-
clickmode='event+select', # Enable interactivity
|
182 |
-
xaxis_tickangle=45, # Rotate x-axis labels 45 degrees
|
183 |
-
margin=dict(t=50, b=150, r=20), # Add bottom margin to prevent label cutoff
|
184 |
-
)
|
185 |
-
return fig
|
186 |
-
|
187 |
-
|
188 |
@st.cache_data
|
189 |
-
def create_map(df, selected_year
|
190 |
-
# Filter data by selected year
|
191 |
filtered_df = df[df['Year'] == selected_year]
|
192 |
-
|
193 |
-
# Filter further by selected severity if provided
|
194 |
-
if selected_severity:
|
195 |
-
filtered_df = filtered_df[filtered_df['Injuryseverity'] == selected_severity]
|
196 |
-
|
197 |
-
# Remove rows with missing latitude or longitude
|
198 |
-
filtered_df = filtered_df.dropna(subset=['Latitude', 'Longitude'])
|
199 |
-
|
200 |
-
# Create the map
|
201 |
m = folium.Map(
|
202 |
-
location=[33.4255, -111.9400],
|
203 |
zoom_start=12,
|
204 |
control_scale=True,
|
205 |
tiles='CartoDB positron'
|
206 |
)
|
207 |
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
# Add accident markers
|
212 |
for _, row in filtered_df.iterrows():
|
213 |
folium.Marker(
|
214 |
location=[row['Latitude'], row['Longitude']],
|
@@ -216,11 +135,9 @@ def create_map(df, selected_year, selected_severity=None):
|
|
216 |
icon=folium.Icon(color='red')
|
217 |
).add_to(marker_cluster)
|
218 |
|
219 |
-
# Add heatmap
|
220 |
heat_data = filtered_df[['Latitude', 'Longitude']].values.tolist()
|
221 |
-
HeatMap(heat_data, radius=15, max_zoom=13, min_opacity=0.3
|
222 |
|
223 |
-
folium.LayerControl().add_to(m)
|
224 |
return m
|
225 |
|
226 |
def create_injuries_fatalities_chart(crash_data, unit_type):
|
@@ -391,7 +308,7 @@ def create_category_distribution_chart(df, selected_category, selected_year):
|
|
391 |
barmode='stack',
|
392 |
xaxis_tickangle=-45,
|
393 |
legend_title='Injury Severity',
|
394 |
-
margin=dict(t=50, b=
|
395 |
)
|
396 |
|
397 |
return fig
|
@@ -428,16 +345,16 @@ def main():
|
|
428 |
|
429 |
st.markdown("""
|
430 |
**Team Members:**
|
431 |
-
- Janhavi Tushar Zarapkar
|
432 |
- Hangyue Zhang ([email protected])
|
433 |
- Andrew Nam ([email protected])
|
434 |
- Nirmal Attarde ([email protected])
|
435 |
-
- Maanas Sandeep
|
436 |
""")
|
437 |
|
438 |
|
439 |
st.markdown("""
|
440 |
-
|
441 |
This dataset contains detailed information about traffic accidents in the city of **Tempe**. It includes various attributes of the accidents, such as the severity of injuries, the demographics of the drivers involved, the locations of the incidents, and the conditions at the time of the accidents. The dataset covers accidents that occurred over several years, with data on factors like **weather conditions**, **road surface conditions**, the **time of day**, and the type of **violations** (e.g., alcohol or drug use) that may have contributed to the accident.
|
442 |
|
443 |
The data was sourced from **Tempe City's traffic incident reports** and provides a comprehensive view of the factors influencing road safety and accident severity in the city. By analyzing this dataset, we can gain insights into the key contributors to traffic incidents and uncover trends that could help improve traffic safety measures, urban planning, and law enforcement policies in the city.
|
@@ -450,21 +367,14 @@ def main():
|
|
450 |
|
451 |
if 'Weather' not in df.columns:
|
452 |
df['Weather'] = 'Unknown'
|
453 |
-
|
454 |
-
if 'selected_violation' not in st.session_state:
|
455 |
-
st.session_state['selected_violation'] = None
|
456 |
-
|
457 |
-
if "selected_severity" not in st.session_state:
|
458 |
-
st.session_state["selected_severity"] = None
|
459 |
|
460 |
-
|
461 |
# Create tabs for different visualizations
|
462 |
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
463 |
"Crash Trend",
|
464 |
-
"
|
465 |
"Distribution by Category",
|
466 |
"Crash Injuries/Fatalities",
|
467 |
-
"
|
468 |
])
|
469 |
|
470 |
with tab1:
|
@@ -482,8 +392,6 @@ def main():
|
|
482 |
margin=dict(l=50, r=50, t=50, b=50)
|
483 |
)
|
484 |
st.plotly_chart(trend_fig, use_container_width=True)
|
485 |
-
|
486 |
-
|
487 |
|
488 |
with desc_col:
|
489 |
st.markdown("""
|
@@ -500,7 +408,6 @@ def main():
|
|
500 |
* **Dynamic Title**: The chart updates its title to reflect the selected weather condition or "All Conditions" for the overall trend.
|
501 |
|
502 |
**Insights:**
|
503 |
-
|
504 |
This chart helps uncover:
|
505 |
* Annual fluctuations in crash incidents.
|
506 |
* Correlations between weather conditions and crash frequencies.
|
@@ -512,24 +419,12 @@ def main():
|
|
512 |
age_groups = ['All Ages', '16-25', '26-35', '36-45', '46-55', '56-65', '65+']
|
513 |
selected_age = st.selectbox('Select Age Group:', age_groups)
|
514 |
|
515 |
-
chart_col, desc_col = st.columns([
|
516 |
|
517 |
with chart_col:
|
518 |
# Create and display chart
|
519 |
-
fig
|
520 |
-
|
521 |
-
clicked_points = plotly_events(fig, click_event=True, override_height=600, override_width="100%")
|
522 |
-
|
523 |
-
if clicked_points:
|
524 |
-
selected_violation = clicked_points[0]['x']
|
525 |
-
if selected_violation != st.session_state['selected_violation']:
|
526 |
-
st.session_state['selected_violation'] = selected_violation
|
527 |
-
|
528 |
-
# If a violation is selected, display the pie chart --> added for part3 (interactive pie chart)
|
529 |
-
if st.session_state['selected_violation']:
|
530 |
-
# pie_chart = create_interactive_pie_chart(violations, st.session_state['selected_violation'])
|
531 |
-
pie_chart = create_interactive_pie_chart(violations, st.session_state['selected_violation'], selected_age) # dynamically update pie chart's title
|
532 |
-
st.plotly_chart(pie_chart, use_container_width=True)
|
533 |
|
534 |
# Display statistics
|
535 |
if selected_age == 'All Ages':
|
@@ -540,46 +435,37 @@ def main():
|
|
540 |
(df['Age_Group_Drv2'] == selected_age)
|
541 |
])
|
542 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
543 |
|
544 |
with desc_col:
|
545 |
st.markdown("""
|
546 |
-
|
547 |
-
|
548 |
-
This section provides an interactive visualization of **crash severities** linked to specific violation types, segmented by driver age groups. It enables a comprehensive analysis of how **age influences crash severity and violation trends**. The visualization is linked to an **interactive pie chart** that updates when a specific bar is selected, displaying the detailed distribution of the selected violation type based on the selected age group.
|
549 |
-
|
550 |
-
---
|
551 |
-
|
552 |
-
## **Key Features**
|
553 |
-
|
554 |
-
### 1. **Age Group Analysis**
|
555 |
-
- Select specific age groups (e.g., "16-25", "65+") or analyze all ages to explore correlations between:
|
556 |
-
- Age
|
557 |
-
- Violation type
|
558 |
-
- Crash severity
|
559 |
-
- Understand how different age groups are involved in various types of violations.
|
560 |
-
|
561 |
-
### 2. **Violation Breakdown**
|
562 |
-
- Examine the most frequent violations contributing to traffic accidents for each age group.
|
563 |
-
- View detailed statistics showing the distribution of violation types.
|
564 |
-
|
565 |
-
### 3. **Understanding Severity Level**
|
566 |
-
- Identify the proportion of severity levels for a specific violation type based on different age groups.
|
567 |
-
- Investigate detailed severity patterns for each violation type across age groups.
|
568 |
-
|
569 |
-
---
|
570 |
-
|
571 |
-
## **Insights**
|
572 |
-
|
573 |
-
- **Identifies High-Risk Behaviors:**
|
574 |
-
- Highlights risky behaviors such as reckless driving in younger drivers or impaired driving in older groups.
|
575 |
|
576 |
-
|
577 |
-
|
|
|
|
|
|
|
|
|
578 |
|
579 |
-
|
580 |
-
|
|
|
581 |
|
582 |
-
|
|
|
|
|
|
|
583 |
""")
|
584 |
|
585 |
with tab3:
|
@@ -614,7 +500,7 @@ def main():
|
|
614 |
## Distribution of Incidents by {selected_category}
|
615 |
This visualization explores the distribution of traffic incidents across various categories, such as Collision Manner, Weather, Surface Condition, Alcohol Use, and Driver Gender. Each bar represents a specific category value (e.g., "Male" or "Female" for Gender), and the bars are divided into segments based on Injury Severity (e.g., Minor, Moderate, Serious, Fatal).
|
616 |
|
617 |
-
**Key
|
618 |
* Interactive Filters: Select a category and filter by year to analyze trends over time.
|
619 |
* Insightful Tooltips: Hover over each segment to view the exact count and percentage of incidents for a given severity level.
|
620 |
* Comparative Analysis: Quickly identify how different conditions or behaviors correlate with injury severity.
|
@@ -676,83 +562,37 @@ def main():
|
|
676 |
years = sorted(df['Year'].unique())
|
677 |
selected_year = st.selectbox('Select Year:', years)
|
678 |
|
679 |
-
|
680 |
-
viz_col, desc_col = st.columns([6, 4])
|
681 |
|
682 |
-
with
|
683 |
-
# First add bar chart
|
684 |
-
st.subheader("Severity-Location Analysis")
|
685 |
-
bar_fig = create_map_bar_chart(df, selected_year)
|
686 |
-
|
687 |
-
# Capture click events with bar chart
|
688 |
-
clicked_points = plotly_events(
|
689 |
-
bar_fig,
|
690 |
-
click_event=True,
|
691 |
-
override_height=300,
|
692 |
-
override_width="100%"
|
693 |
-
)
|
694 |
-
|
695 |
-
if clicked_points:
|
696 |
-
selected_severity = clicked_points[0]['x']
|
697 |
-
st.session_state["selected_severity"] = selected_severity
|
698 |
-
|
699 |
-
# Show currently selected severity
|
700 |
-
st.write(f"Selected Severity: {st.session_state['selected_severity'] if st.session_state['selected_severity'] else 'All'}")
|
701 |
-
|
702 |
-
# Add map below bar chart
|
703 |
-
st.subheader("Accident Locations")
|
704 |
map_placeholder = st.empty()
|
705 |
with map_placeholder:
|
706 |
-
m = create_map(df, selected_year
|
707 |
map_data = st_folium(
|
708 |
m,
|
709 |
width=None,
|
710 |
-
height=
|
711 |
-
key=f"map_{selected_year}
|
712 |
returned_objects=["null_drawing"]
|
713 |
)
|
714 |
-
|
715 |
with desc_col:
|
716 |
st.markdown("""
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
Combines Streamlit and Folium, with Plotly events linking the visualizations.
|
732 |
-
---
|
733 |
-
## **Design**
|
734 |
-
- **Bar Chart:**
|
735 |
-
- Uses a calm blue color for clarity.
|
736 |
-
- **Map:**
|
737 |
-
- Uses **CartoDB tiles** with red markers and heatmaps for visibility.
|
738 |
-
---
|
739 |
-
## **Insights**
|
740 |
-
- **Severity Patterns:**
|
741 |
-
The bar chart reveals accident trends across severity levels.
|
742 |
-
- **Spatial Trends:**
|
743 |
-
The map identifies high-risk accident hotspots.
|
744 |
-
- **Yearly and Severity Insights:**
|
745 |
-
Filters help uncover temporal and severity-related patterns, aiding traffic safety analysis.
|
746 |
""")
|
747 |
-
st.markdown("---")
|
748 |
-
|
749 |
-
# Add conclusion section
|
750 |
-
st.markdown("# FP3 Conclusion")
|
751 |
-
|
752 |
-
st.markdown("""
|
753 |
-
TODO
|
754 |
-
""")
|
755 |
-
|
756 |
|
757 |
|
758 |
if __name__ == "__main__":
|
|
|
3 |
import plotly.express as px
|
4 |
import altair as alt
|
5 |
import folium
|
|
|
6 |
from folium.plugins import HeatMap, MarkerCluster
|
7 |
from streamlit_folium import st_folium
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
@st.cache_data
|
10 |
def load_and_preprocess_data(file_path):
|
11 |
# Read the data
|
|
|
68 |
y='count',
|
69 |
color='Severity',
|
70 |
title=f'Crash Severity Distribution by Violation Type - {age_group}',
|
|
|
71 |
labels={'count': 'Number of Incidents', 'Violation': 'Violation Type'},
|
72 |
+
height=600
|
73 |
)
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
fig.update_layout(
|
76 |
xaxis_tickangle=-45,
|
77 |
+
legend_title='Severity Level',
|
78 |
+
barmode='stack'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
)
|
80 |
|
81 |
+
return fig
|
|
|
82 |
|
83 |
def get_top_violations(df, age_group):
|
84 |
# Calculate total incidents for the age group
|
85 |
if age_group == 'All Ages':
|
86 |
+
total_incidents = len(df) # 总样本数
|
87 |
# Get violations for all ages
|
88 |
violations = pd.concat([
|
89 |
df['Violation1_Drv1'].value_counts(),
|
|
|
115 |
|
116 |
return violations_df.head()
|
117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
@st.cache_data
|
119 |
+
def create_map(df, selected_year):
|
|
|
120 |
filtered_df = df[df['Year'] == selected_year]
|
121 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
m = folium.Map(
|
123 |
+
location=[33.4255, -111.9400],
|
124 |
zoom_start=12,
|
125 |
control_scale=True,
|
126 |
tiles='CartoDB positron'
|
127 |
)
|
128 |
|
129 |
+
marker_cluster = MarkerCluster().add_to(m)
|
130 |
+
|
|
|
|
|
131 |
for _, row in filtered_df.iterrows():
|
132 |
folium.Marker(
|
133 |
location=[row['Latitude'], row['Longitude']],
|
|
|
135 |
icon=folium.Icon(color='red')
|
136 |
).add_to(marker_cluster)
|
137 |
|
|
|
138 |
heat_data = filtered_df[['Latitude', 'Longitude']].values.tolist()
|
139 |
+
HeatMap(heat_data, radius=15, max_zoom=13, min_opacity=0.3).add_to(m)
|
140 |
|
|
|
141 |
return m
|
142 |
|
143 |
def create_injuries_fatalities_chart(crash_data, unit_type):
|
|
|
308 |
barmode='stack',
|
309 |
xaxis_tickangle=-45,
|
310 |
legend_title='Injury Severity',
|
311 |
+
margin=dict(t=50, b=100),
|
312 |
)
|
313 |
|
314 |
return fig
|
|
|
345 |
|
346 |
st.markdown("""
|
347 |
**Team Members:**
|
348 |
+
- Janhavi Tushar Zarapkar ([email protected])
|
349 |
- Hangyue Zhang ([email protected])
|
350 |
- Andrew Nam ([email protected])
|
351 |
- Nirmal Attarde ([email protected])
|
352 |
+
- Maanas Sandeep Agrawa ([email protected])
|
353 |
""")
|
354 |
|
355 |
|
356 |
st.markdown("""
|
357 |
+
### Introduction to the Traffic Accident Dataset
|
358 |
This dataset contains detailed information about traffic accidents in the city of **Tempe**. It includes various attributes of the accidents, such as the severity of injuries, the demographics of the drivers involved, the locations of the incidents, and the conditions at the time of the accidents. The dataset covers accidents that occurred over several years, with data on factors like **weather conditions**, **road surface conditions**, the **time of day**, and the type of **violations** (e.g., alcohol or drug use) that may have contributed to the accident.
|
359 |
|
360 |
The data was sourced from **Tempe City's traffic incident reports** and provides a comprehensive view of the factors influencing road safety and accident severity in the city. By analyzing this dataset, we can gain insights into the key contributors to traffic incidents and uncover trends that could help improve traffic safety measures, urban planning, and law enforcement policies in the city.
|
|
|
367 |
|
368 |
if 'Weather' not in df.columns:
|
369 |
df['Weather'] = 'Unknown'
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
|
|
|
371 |
# Create tabs for different visualizations
|
372 |
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
373 |
"Crash Trend",
|
374 |
+
"Crash Statistics",
|
375 |
"Distribution by Category",
|
376 |
"Crash Injuries/Fatalities",
|
377 |
+
"Crash Map"
|
378 |
])
|
379 |
|
380 |
with tab1:
|
|
|
392 |
margin=dict(l=50, r=50, t=50, b=50)
|
393 |
)
|
394 |
st.plotly_chart(trend_fig, use_container_width=True)
|
|
|
|
|
395 |
|
396 |
with desc_col:
|
397 |
st.markdown("""
|
|
|
408 |
* **Dynamic Title**: The chart updates its title to reflect the selected weather condition or "All Conditions" for the overall trend.
|
409 |
|
410 |
**Insights:**
|
|
|
411 |
This chart helps uncover:
|
412 |
* Annual fluctuations in crash incidents.
|
413 |
* Correlations between weather conditions and crash frequencies.
|
|
|
419 |
age_groups = ['All Ages', '16-25', '26-35', '36-45', '46-55', '56-65', '65+']
|
420 |
selected_age = st.selectbox('Select Age Group:', age_groups)
|
421 |
|
422 |
+
chart_col, desc_col = st.columns([7, 3])
|
423 |
|
424 |
with chart_col:
|
425 |
# Create and display chart
|
426 |
+
fig = create_severity_violation_chart(df, selected_age)
|
427 |
+
st.plotly_chart(fig, use_container_width=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
|
429 |
# Display statistics
|
430 |
if selected_age == 'All Ages':
|
|
|
435 |
(df['Age_Group_Drv2'] == selected_age)
|
436 |
])
|
437 |
|
438 |
+
# Create two columns for statistics
|
439 |
+
col1, col2 = st.columns(2)
|
440 |
+
|
441 |
+
with col1:
|
442 |
+
st.markdown(f"### Total Incidents")
|
443 |
+
st.markdown(f"**{total_incidents:,}** incidents for {selected_age}")
|
444 |
+
|
445 |
+
with col2:
|
446 |
+
st.markdown("### Top Violations")
|
447 |
+
top_violations = get_top_violations(df, selected_age)
|
448 |
+
st.table(top_violations)
|
449 |
|
450 |
with desc_col:
|
451 |
st.markdown("""
|
452 |
+
## Severity of Violations Across Age Groups
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
453 |
|
454 |
+
This section provides an interactive visualization of crash severities linked to specific violation types, segmented by driver age groups. It enables a comprehensive analysis of how age influences crash severity and violation trends.
|
455 |
+
|
456 |
+
**Key Features:**
|
457 |
+
1. **Age Group Analysis**:
|
458 |
+
* Select specific age groups (e.g., "16-25", "65+") or analyze all ages to explore correlations between age, violation type, and crash severity.
|
459 |
+
* Understand how different age groups are involved in various types of violations.
|
460 |
|
461 |
+
2. **Violation Breakdown**:
|
462 |
+
* Examine the most frequent violations contributing to traffic accidents for each age group.
|
463 |
+
* View detailed statistics showing the distribution of violation types.
|
464 |
|
465 |
+
**Insights:**
|
466 |
+
* Identifies high-risk behaviors within specific age groups, such as reckless driving in younger drivers or impaired driving in older groups.
|
467 |
+
* Highlights which violations are associated with more severe outcomes, aiding targeted safety interventions and public awareness campaigns.
|
468 |
+
* Supports data-driven decision making for age-specific traffic safety programs.
|
469 |
""")
|
470 |
|
471 |
with tab3:
|
|
|
500 |
## Distribution of Incidents by {selected_category}
|
501 |
This visualization explores the distribution of traffic incidents across various categories, such as Collision Manner, Weather, Surface Condition, Alcohol Use, and Driver Gender. Each bar represents a specific category value (e.g., "Male" or "Female" for Gender), and the bars are divided into segments based on Injury Severity (e.g., Minor, Moderate, Serious, Fatal).
|
502 |
|
503 |
+
**Key features include:**
|
504 |
* Interactive Filters: Select a category and filter by year to analyze trends over time.
|
505 |
* Insightful Tooltips: Hover over each segment to view the exact count and percentage of incidents for a given severity level.
|
506 |
* Comparative Analysis: Quickly identify how different conditions or behaviors correlate with injury severity.
|
|
|
562 |
years = sorted(df['Year'].unique())
|
563 |
selected_year = st.selectbox('Select Year:', years)
|
564 |
|
565 |
+
map_col, desc_col = st.columns([7, 3])
|
|
|
566 |
|
567 |
+
with map_col:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
568 |
map_placeholder = st.empty()
|
569 |
with map_placeholder:
|
570 |
+
m = create_map(df, selected_year)
|
571 |
map_data = st_folium(
|
572 |
m,
|
573 |
width=None,
|
574 |
+
height=800,
|
575 |
+
key=f"map_{selected_year}",
|
576 |
returned_objects=["null_drawing"]
|
577 |
)
|
578 |
+
|
579 |
with desc_col:
|
580 |
st.markdown("""
|
581 |
+
### Traffic Crash Location Map
|
582 |
+
This interactive map visualizes traffic accidents in Tempe for the selected year. It combines **marker clustering** and a **heatmap** to show:
|
583 |
+
1. **Accident Markers**: Red markers indicate individual accidents, with popups displaying the coordinates, date/time, and severity of each incident.
|
584 |
+
2. **Heatmap**: The heatmap highlights accident hotspots with colors ranging from blue (low frequency) to yellow (moderate) and red (high frequency), showing areas with more frequent accidents.
|
585 |
+
|
586 |
+
**Key Features:**
|
587 |
+
* **Interactive Year Selection**: Users can select a year to view accidents for that specific time.
|
588 |
+
* **Accident Patterns**: The map reveals accident-prone areas and severity patterns, helping identify dangerous locations.
|
589 |
+
|
590 |
+
**Color Scheme:**
|
591 |
+
* **Red**: Individual accident markers.
|
592 |
+
* **Blue to Red**: Heatmap colors indicate accident frequency, from low (blue) to high (red).
|
593 |
+
|
594 |
+
This map provides insights into accident trends and can help guide safety improvements in the city.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
595 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
596 |
|
597 |
|
598 |
if __name__ == "__main__":
|