namdini commited on
Commit
a853711
·
verified ·
1 Parent(s): 575cab5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -63
app.py CHANGED
@@ -3,11 +3,11 @@ 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
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
11
  severity_colors = {
12
  "No Injury": "#1f77b4",
13
  "Possible Injury": "#aec7e8",
@@ -88,29 +88,13 @@ def create_severity_violation_chart(df, age_group=None):
88
  fig.update_layout(
89
  xaxis_tickangle=-45,
90
  legend_title='Severity Level',
91
- barmode='stack'
 
 
92
  )
93
 
94
  # return fig
95
- return fig, violations # this return is needed for part3
96
-
97
- # added interactivity pie plot for part3
98
- def create_interactive_pie_chart(violations, selected_violation):
99
- # Filter data based on selected violation
100
- filtered_data = violations[violations['Violation'] == selected_violation]
101
-
102
- # Create a pie chart for severity distribution of the selected violation type
103
- fig = px.pie(
104
- filtered_data,
105
- names='Severity',
106
- values='count',
107
- title=f'Severity Level Distribution for Violation: {selected_violation}',
108
- height=400,
109
- color_discrete_map=severity_colors
110
- )
111
-
112
- return fig
113
-
114
 
115
  def get_top_violations(df, age_group):
116
  if age_group == 'All Ages':
@@ -136,6 +120,23 @@ def get_top_violations(df, age_group):
136
 
137
  return violations_df.head()
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  @st.cache_data
140
  def create_map(df, selected_year):
141
  filtered_df = df[df['Year'] == selected_year]
@@ -335,7 +336,53 @@ def create_category_distribution_chart(df, selected_category, selected_year):
335
  return fig
336
 
337
  def main():
338
- st.title('Traffic Crash Analysis')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
  # Load data
341
  df = load_and_preprocess_data('1.08_Crash_Data_Report_(detail).csv')
@@ -343,7 +390,7 @@ def main():
343
  if 'Weather' not in df.columns:
344
  df['Weather'] = 'Unknown'
345
 
346
- # Initialize session state to store selected violation --> for part3
347
  if 'selected_violation' not in st.session_state:
348
  st.session_state['selected_violation'] = None
349
 
@@ -357,28 +404,22 @@ def main():
357
 
358
  # Create and display chart
359
  # fig = create_severity_violation_chart(df, selected_age)
360
- fig, violations = create_severity_violation_chart(df, selected_age) # --> for part3
361
-
362
- # # Get unique violations from the chart data (New line) --> for part3
363
- # unique_violations = violations['Violation'].unique()
364
-
365
  # st.plotly_chart(fig, use_container_width=True)
366
 
367
  # Display the first bar chart and capture click events using plotly_events
368
- # clicked_points = plotly_events(fig, click_event=True)
369
- clicked_points = plotly_events(fig, click_event=True, override_height=600, override_width="100%") # for part3
370
 
371
- # If a bar is clicked, update the selected_violation in session_state
372
  if clicked_points:
373
  selected_violation = clicked_points[0]['x']
374
  if selected_violation != st.session_state['selected_violation']:
375
  st.session_state['selected_violation'] = selected_violation
376
 
377
- # If a violation is selected, display the pie chart
378
  if st.session_state['selected_violation']:
379
  pie_chart = create_interactive_pie_chart(violations, st.session_state['selected_violation'])
380
  st.plotly_chart(pie_chart, use_container_width=True)
381
-
382
 
383
  # Display statistics
384
  if selected_age == 'All Ages':
@@ -406,18 +447,40 @@ def main():
406
  years = sorted(df['Year'].unique())
407
  selected_year = st.selectbox('Select Year:', years)
408
 
409
- # Create and display map
410
- st.markdown("### Crash Location Map")
411
- map_placeholder = st.empty()
412
- with map_placeholder:
413
- m = create_map(df, selected_year)
414
- map_data = st_folium(
415
- m,
416
- width=800,
417
- height=600,
418
- key=f"map_{selected_year}",
419
- returned_objects=["null_drawing"]
420
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
 
422
  with tab3:
423
  # Weather condition filter
@@ -425,9 +488,38 @@ def main():
425
  selected_weather = st.selectbox('Select Weather Condition:', weather)
426
 
427
  # Create and display line graph
428
- st.markdown("### Crash Trend Over Time")
429
- trend_fig = create_crash_trend_chart(df, selected_weather)
430
- st.plotly_chart(trend_fig, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
 
432
  with tab4:
433
  # Dropdown for Unit Type selection
@@ -439,18 +531,62 @@ def main():
439
  unit_type_pairs = sorted(list(unit_type_pairs))
440
  unit_type = st.selectbox("Select Unit Type Pair", options=['Total'] + unit_type_pairs)
441
 
442
- # Create 5th Visualization: Injuries and fatalities chart
443
- injuries_fatalities_chart = create_injuries_fatalities_chart(df, unit_type)
444
- st.altair_chart(injuries_fatalities_chart, use_container_width=True)
445
- st.markdown("""
446
- This line chart shows the **total number of injuries and fatalities by month for the selected unit type pair**. The blue line represents total injuries, while the red line represents total fatalities. Observing the trends over the months can help identify any seasonal patterns or peaks in traffic incidents involving specific unit types.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
 
448
- - **Total Injuries**: The blue line indicates how injuries vary over different months, highlighting any particular spikes or declines.
449
- - **Total Fatalities**: The red line shows the trend for fatalities, which is generally much lower compared to injuries.
450
- - **Unit Types**: The dropdown selection allows users to filter the data by specific unit type pairs (e.g., Driver vs Pedestrian) or view the overall trend across all types.
451
 
452
- This visualization aims to provide an intuitive understanding of how injuries and fatalities are distributed across the year, helping stakeholders develop targeted safety measures.
453
- """)
454
 
455
  with tab5:
456
  # Dropdown for category selection
@@ -468,10 +604,31 @@ def main():
468
  years = ['All Years'] + sorted(df['Year'].dropna().unique().astype(int).tolist())
469
  selected_year = st.selectbox("Select Year:", years)
470
 
471
- # Generate and display the distribution chart
472
- st.markdown(f"### Distribution of Incidents by {selected_category}")
473
- distribution_chart = create_category_distribution_chart(df, selected_category, selected_year)
474
- st.plotly_chart(distribution_chart, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
 
476
 
477
  if __name__ == "__main__":
 
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",
 
88
  fig.update_layout(
89
  xaxis_tickangle=-45,
90
  legend_title='Severity Level',
91
+ barmode='stack',
92
+ margin=dict(t=50, b=150), # Increase bottom margin to avoid pruning
93
+ xaxis=dict(automargin=True)
94
  )
95
 
96
  # return fig
97
+ return fig, violations
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
  def get_top_violations(df, age_group):
100
  if age_group == 'All Ages':
 
120
 
121
  return violations_df.head()
122
 
123
+ # added interactivity pie plot for part3 (linked with crash stats visualization)
124
+ def create_interactive_pie_chart(violations, selected_violation):
125
+ # Filter data based on selected violation
126
+ filtered_data = violations[violations['Violation'] == selected_violation]
127
+
128
+ # Create a pie chart for severity distribution of the selected violation type
129
+ fig = px.pie(
130
+ filtered_data,
131
+ names='Severity',
132
+ values='count',
133
+ title=f'Severity Level Distribution for Violation: {selected_violation}',
134
+ height=600,
135
+ color_discrete_map=severity_colors
136
+ )
137
+
138
+ return fig
139
+
140
  @st.cache_data
141
  def create_map(df, selected_year):
142
  filtered_df = df[df['Year'] == selected_year]
 
336
  return fig
337
 
338
  def main():
339
+ st.set_page_config(page_title="Terrific Tempe Traffic", layout="wide")
340
+
341
+ st.markdown("""
342
+ <style>
343
+ .reportview-container {
344
+ font-size: 20px;
345
+ }
346
+ h1, h2, h3, h4, h5, h6 {
347
+ font-size: 150%;
348
+ }
349
+ p {
350
+ font-size: 125%;
351
+ }
352
+ </style>
353
+ """, unsafe_allow_html=True)
354
+
355
+
356
+ st.markdown("""
357
+ <style>
358
+ .title {
359
+ text-align: center;
360
+ padding: 25px;
361
+ }
362
+ </style>
363
+ """, unsafe_allow_html=True)
364
+
365
+ st.markdown("<div class='title'><h1> Accident Analysis for City of Tempe, Arizona </h1></div>", unsafe_allow_html=True)
366
+
367
+
368
+ st.markdown("""
369
+ **Team Members:**
370
+ - Janhavi Tushar Zarapkar (jzarap2@illinois.edu)
371
+ - Hangyue Zhang (hz85@illinois.edu)
372
+ - Andrew Nam (donginn2@illinois.edu)
373
+ - Nirmal Attarde (natta4@illinois.edu)
374
+ - Maanas Sandeep Agrawa (msa17@illinois.edu)
375
+ """)
376
+
377
+
378
+ st.markdown("""
379
+ ### Introduction to the Traffic Accident Dataset
380
+ 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.
381
+
382
+ 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.
383
+ """)
384
+
385
+
386
 
387
  # Load data
388
  df = load_and_preprocess_data('1.08_Crash_Data_Report_(detail).csv')
 
390
  if 'Weather' not in df.columns:
391
  df['Weather'] = 'Unknown'
392
 
393
+ # Initialize session state to store selected violation --> added for part3 (interactive pie chart)
394
  if 'selected_violation' not in st.session_state:
395
  st.session_state['selected_violation'] = None
396
 
 
404
 
405
  # Create and display chart
406
  # fig = create_severity_violation_chart(df, selected_age)
407
+ fig, violations = create_severity_violation_chart(df, selected_age) # --> for part3 (interactive pie chart)
 
 
 
 
408
  # st.plotly_chart(fig, use_container_width=True)
409
 
410
  # Display the first bar chart and capture click events using plotly_events
411
+ clicked_points = plotly_events(fig, click_event=True, override_height=600, override_width="100%") # added for part3 (interactive pie chart)
 
412
 
413
+ # If a bar is clicked, update the selected_violation in session_state --> added for part3 (interactive pie chart)
414
  if clicked_points:
415
  selected_violation = clicked_points[0]['x']
416
  if selected_violation != st.session_state['selected_violation']:
417
  st.session_state['selected_violation'] = selected_violation
418
 
419
+ # If a violation is selected, display the pie chart --> added for part3 (interactive pie chart)
420
  if st.session_state['selected_violation']:
421
  pie_chart = create_interactive_pie_chart(violations, st.session_state['selected_violation'])
422
  st.plotly_chart(pie_chart, use_container_width=True)
 
423
 
424
  # Display statistics
425
  if selected_age == 'All Ages':
 
447
  years = sorted(df['Year'].unique())
448
  selected_year = st.selectbox('Select Year:', years)
449
 
450
+ map_col, desc_col = st.columns([7, 3])
451
+
452
+ with map_col:
453
+ # Create and display map
454
+ st.markdown("### Crash Location Map")
455
+ map_placeholder = st.empty()
456
+ with map_placeholder:
457
+ m = create_map(df, selected_year)
458
+ map_data = st_folium(
459
+ m,
460
+ width=None,
461
+ height=800,
462
+ key=f"map_{selected_year}",
463
+ returned_objects=["null_drawing"]
464
+ )
465
+
466
+ with desc_col:
467
+ st.markdown("""
468
+ ### Traffic Crash Location Map
469
+ This interactive map visualizes traffic accidents in Tempe for the selected year. It combines **marker clustering** and a **heatmap** to show:
470
+ 1. **Accident Markers**: Red markers indicate individual accidents, with popups displaying the coordinates, date/time, and severity of each incident.
471
+ 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.
472
+
473
+ **Key Features:**
474
+ * **Interactive Year Selection**: Users can select a year to view accidents for that specific time.
475
+ * **Accident Patterns**: The map reveals accident-prone areas and severity patterns, helping identify dangerous locations.
476
+
477
+ **Color Scheme:**
478
+ * **Red**: Individual accident markers.
479
+ * **Blue to Red**: Heatmap colors indicate accident frequency, from low (blue) to high (red).
480
+
481
+ This map provides insights into accident trends and can help guide safety improvements in the city.
482
+ """)
483
+
484
 
485
  with tab3:
486
  # Weather condition filter
 
488
  selected_weather = st.selectbox('Select Weather Condition:', weather)
489
 
490
  # Create and display line graph
491
+
492
+ trend_col, desc_col = st.columns([7, 3])
493
+
494
+ with trend_col:
495
+ st.markdown("### Crash Trend Over Time")
496
+ trend_fig = create_crash_trend_chart(df, selected_weather)
497
+ # Update the figure layout for larger size
498
+ trend_fig.update_layout(
499
+ height=800, # Increased height
500
+ width=None, # Let width be responsive
501
+ margin=dict(l=50, r=50, t=50, b=50)
502
+ )
503
+ st.plotly_chart(trend_fig, use_container_width=True)
504
+
505
+ with desc_col:
506
+ st.markdown("""
507
+ ## **Crash Trend Over Time**
508
+ This interactive line chart visualizes the trend of unique traffic crashes over the years, optionally filtered by weather conditions. It highlights how crash frequency changes over time, helping identify trends and potential contributing factors.
509
+ **Key Features:**
510
+ * **Time Trend Analysis**: Displays the total number of unique crashes for each year, showing long-term patterns.
511
+ * **Weather Filter**: Users can filter the data by weather conditions (e.g., "Rainy", "Sunny") to analyze how weather impacts crash trends.
512
+ * **Interactive Tooltips**: Hovering over data points reveals the exact crash count for each year, providing detailed insights.
513
+ **Color Scheme and Design:**
514
+ * **Line and Markers**: A smooth line connects data points, with prominent markers for each year to highlight trends clearly.
515
+ * **Dynamic Title**: The chart updates its title to reflect the selected weather condition or "All Conditions" for the overall trend.
516
+ **Insights:**
517
+ This chart helps uncover:
518
+ * Annual fluctuations in crash incidents.
519
+ * Correlations between weather conditions and crash frequencies.
520
+ * Historical patterns that can guide future safety measures and urban planning decisions
521
+ """)
522
+
523
 
524
  with tab4:
525
  # Dropdown for Unit Type selection
 
531
  unit_type_pairs = sorted(list(unit_type_pairs))
532
  unit_type = st.selectbox("Select Unit Type Pair", options=['Total'] + unit_type_pairs)
533
 
534
+ # # Create 5th Visualization: Injuries and fatalities chart
535
+ # injuries_fatalities_chart = create_injuries_fatalities_chart(df, unit_type)
536
+ # st.altair_chart(injuries_fatalities_chart, use_container_width=True)
537
+
538
+ # st.markdown("""
539
+ # This line chart shows the **total number of injuries and fatalities by month for the selected unit type pair**. The blue line represents total injuries, while the red line represents total fatalities. Observing the trends over the months can help identify any seasonal patterns or peaks in traffic incidents involving specific unit types.
540
+
541
+ # - **Total Injuries**: The blue line indicates how injuries vary over different months, highlighting any particular spikes or declines.
542
+ # - **Total Fatalities**: The red line shows the trend for fatalities, which is generally much lower compared to injuries.
543
+ # - **Unit Types**: The dropdown selection allows users to filter the data by specific unit type pairs (e.g., Driver vs Pedestrian) or view the overall trend across all types.
544
+
545
+ # This visualization aims to provide an intuitive understanding of how injuries and fatalities are distributed across the year, helping stakeholders develop targeted safety measures.
546
+ # """)
547
+
548
+ chart_col, desc_col = st.columns([7, 3])
549
+
550
+ with chart_col:
551
+ # Create 5th Visualization: Injuries and fatalities chart
552
+ injuries_fatalities_chart = create_injuries_fatalities_chart(df, unit_type)
553
+ injuries_fatalities_chart = injuries_fatalities_chart.properties(
554
+ height=800 # Make the chart taller to match the description column
555
+ )
556
+ st.altair_chart(injuries_fatalities_chart, use_container_width=True)
557
+
558
+ with desc_col:
559
+ st.markdown("""
560
+ ## Injuries and Fatalities Trends
561
+
562
+ This line chart shows the **total number of injuries and fatalities by month for the selected unit type pair**. The visualization helps identify seasonal patterns and critical trends in traffic incidents involving specific unit types.
563
+
564
+ **Key Features:**
565
+ * **Injuries Trend** (Blue Line)
566
+ - Tracks monthly injury counts
567
+ - Shows seasonal variations
568
+ - Identifies peak incident periods
569
+
570
+ * **Fatalities Trend** (Red Line)
571
+ - Monitors monthly fatality counts
572
+ - Generally lower than injuries
573
+ - Highlights critical safety concerns
574
+
575
+ * **Interactive Selection**
576
+ - Filter by specific unit type pairs
577
+ - Compare different vehicle combinations
578
+ - View overall trends across all types
579
+
580
+ **Applications:**
581
+ - Identify high-risk months
582
+ - Guide seasonal safety measures
583
+ - Inform emergency response planning
584
+ - Support targeted intervention strategies
585
+
586
+ This visualization aids stakeholders in developing effective safety measures and resource allocation strategies throughout the year.
587
+ """)
588
 
 
 
 
589
 
 
 
590
 
591
  with tab5:
592
  # Dropdown for category selection
 
604
  years = ['All Years'] + sorted(df['Year'].dropna().unique().astype(int).tolist())
605
  selected_year = st.selectbox("Select Year:", years)
606
 
607
+ chart_col, desc_col = st.columns([7, 3])
608
+
609
+ with chart_col:
610
+ st.markdown(f"### Distribution of Incidents by {selected_category}")
611
+ distribution_chart = create_category_distribution_chart(df, selected_category, selected_year)
612
+ # Update the figure layout for larger size
613
+ distribution_chart.update_layout(
614
+ height=800, # Increased height
615
+ width=None, # Let width be responsive
616
+ margin=dict(l=50, r=50, t=50, b=50)
617
+ )
618
+ st.plotly_chart(distribution_chart, use_container_width=True)
619
+
620
+ with desc_col:
621
+ st.markdown("""
622
+ ## Distribution by Category
623
+ 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).
624
+
625
+ **Key features include:**
626
+ * Interactive Filters: Select a category and filter by year to analyze trends over time.
627
+ * Insightful Tooltips: Hover over each segment to view the exact count and percentage of incidents for a given severity level.
628
+ * Comparative Analysis: Quickly identify how different conditions or behaviors correlate with injury severity.
629
+
630
+ This chart provides actionable insights into factors contributing to traffic incidents and their outcomes, helping stakeholders target interventions and improve road safety.
631
+ """)
632
 
633
 
634
  if __name__ == "__main__":