| import streamlit as st |
| import pandas as pd |
| import altair as alt |
| from pathlib import Path |
| import plotly.express as px |
|
|
| |
| st.set_page_config( |
| page_title="Analyze Crime Distributions", |
| page_icon="📊", |
| layout="wide" |
| ) |
| st.markdown(""" |
| <style> |
| .title { |
| text-align: center; |
| padding: 25px; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
| |
| st.markdown("<div class='title'><h1> LAPD Crime Insights Dashboard </h1></div>", unsafe_allow_html=True) |
|
|
| |
| st.markdown(""" This application provides a suite of interactive visualizations—pie charts, bar charts, scatter plots, and more—that let you explore crime patterns in the LAPD dataset from multiple angles. Quickly see which offense categories dominate, compare arrest rates against non-arrests, track how crime volumes change over time, and examine geographic hotspots. These insights can help police departments, community organizations, and policymakers allocate resources more effectively and design targeted strategies to improve public safety.""") |
| |
| |
| st.header("Dataset Information") |
| st.markdown( |
| """ |
| - **Source:** LAPD crime incidents dataset |
| - **Rows:** incidents (one per row) |
| - **Columns:** e.g. `crm_cd_desc` (crime type), `arrest` (boolean), `date`, `location_description`, etc. |
| - **Purpose:** Interactive exploration of top crime categories and arrest rates. |
| """ |
| ) |
|
|
| |
| DATA_PATH = Path(__file__).parent / "crime_data.csv" |
|
|
| @st.cache_data |
| def load_data(): |
| return pd.read_csv(DATA_PATH) |
| |
| if st.button("🔄"): |
| st.cache_data.clear() |
| st.toast("Data is refreshed",icon="✅") |
| |
| |
| df = load_data() |
| if df.empty: |
| st.stop() |
| |
| |
| st.header("Data Preview") |
| st.write(f"Total records: {df.shape[0]} | Total columns: {df.shape[1]}") |
| st.dataframe(df.head()) |
|
|
| |
| st.markdown("<div class='title'><h1> Top 10 Crime Type </h1></div>", unsafe_allow_html=True) |
|
|
| years = sorted(df["year"].dropna().astype(int).unique()) |
| |
| options = ["All"] + years |
|
|
| |
| col_empty, col_filter = st.columns([3,1]) |
| with col_filter: |
| selected_year = st.selectbox( |
| "Select Year", |
| options=options, |
| index=0, |
| key="year_filter" |
| ) |
|
|
| |
| if selected_year == "All": |
| filtered = df.copy() |
| else: |
| filtered = df[df["year"] == selected_year] |
|
|
| |
| top_crimes = ( |
| filtered["crm_cd_desc"] |
| .value_counts() |
| .nlargest(10) |
| .rename_axis("Crime Type") |
| .reset_index(name="Count") |
| ) |
| top_crimes["Percentage"] = top_crimes["Count"] / top_crimes["Count"].sum() |
|
|
| |
| st.markdown("### Key Metrics", unsafe_allow_html=True) |
| col1, col2, col3 = st.columns(3) |
| col1.metric( |
| label="Total Incidents", |
| value=f"{len(filtered):,}" |
| ) |
| col2.metric( |
| label="Unique Crime Types", |
| value=f"{filtered['crm_cd_desc'].nunique():,}" |
| ) |
| |
| top_share = top_crimes.iloc[0]["Percentage"] |
| col3.metric( |
| label=f"Share of Top Crime ({top_crimes.iloc[0]['Crime Type']})", |
| value=f"{top_share:.1%}" |
| ) |
|
|
| |
| fig = px.pie( |
| top_crimes, |
| names="Crime Type", |
| values="Count", |
| hole=0.4, |
| color_discrete_sequence=px.colors.sequential.Agsunset, |
| title=" " |
| ) |
|
|
| fig.update_traces( |
| textposition="outside", |
| textinfo="label+percent", |
| pull=[0.05] * len(top_crimes), |
| marker=dict(line=dict(color="white", width=2)) |
| ) |
|
|
| fig.update_layout( |
| legend_title_text="Crime Type", |
| margin=dict(t=60, b=20, l=20, r=20), |
| height=700, |
| title_x=0.5 |
| ) |
|
|
| st.plotly_chart(fig, use_container_width=True) |
| st.markdown(""" The donut chart shows the share of the ten most frequent crime categories in the selected year. At the center, you can see that Vehicle – Stolen is the single largest slice, accounting for roughly 18.7% of all incidents, The remaining five categories each represent between 3%–5% of total incidents—these include miscellaneous crimes, criminal threats, assault with a deadly weapon, burglary, and minor vandalism. By displaying both slice size and percentage labels, the chart makes it easy to compare how dominant property‐related offenses are, versus violent or lesser‐common crimes, in that year’s LAPD data. """) |
|
|