| import streamlit as st |
| import pandas as pd |
| import numpy as np |
| import folium |
| from folium.plugins import MarkerCluster |
| from streamlit_folium import st_folium |
| import plotly.graph_objects as go |
| from plotly.subplots import make_subplots |
| import calendar |
|
|
| st.title("Khai phá dữ liệu giao thông tại thành phố New York") |
| st.markdown("Halo. Minh sumita") |
|
|
| DATA_URL = 'src/nypd-motor-vehicle-collisions.csv' |
|
|
|
|
| @st.cache_data |
| def load_data(nrows): |
| data = pd.read_csv(DATA_URL, nrows=nrows, parse_dates=[['ACCIDENT DATE', 'ACCIDENT TIME']]) |
| data.dropna(subset=['LATITUDE', 'LONGITUDE'], inplace=True) |
| lowercase = lambda x: str(x).lower() |
| data.rename(lowercase, axis='columns', inplace=True) |
| data.rename(columns={'accident date_accident time': 'date/time'}, inplace=True) |
| return data |
|
|
|
|
| data = load_data(10000) |
| original_data = data.copy() |
|
|
| if st.checkbox('Show Raw data'): |
| st.subheader('Raw Data') |
| st.write(data) |
|
|
| st.header('Đâu là nơi có nhiều người bị thương nhất ở thành phố New York?') |
| injured_people = st.slider('Số người bị thương trong các vụ va chạm xe cộ', 0, 20) |
| st.map(data.query('`number of persons injured` >= @injured_people')[['latitude', 'longitude']].dropna(how='any')) |
|
|
| st.header('Có bao nhiêu va chạm xảy ra trong khoảng thời gian?') |
|
|
| min_date = data['date/time'].dt.date.min() |
| max_date = data['date/time'].dt.date.max() |
|
|
| start_date = st.date_input( |
| "Chọn ngày bắt đầu", |
| value=min_date, |
| min_value=min_date, |
| max_value=max_date |
| ) |
|
|
| end_date = st.date_input( |
| "Chọn ngày kết thúc", |
| value=max_date, |
| min_value=min_date, |
| max_value=max_date |
| ) |
|
|
| if start_date > end_date: |
| st.error("Ngày bắt đầu phải nhỏ hơn hoặc bằng ngày kết thúc!") |
| else: |
| st.markdown(f'Xem dữ liệu từ ngày **{start_date}** đến ngày **{end_date}**') |
|
|
| filtered_data = data[(data['date/time'].dt.date >= start_date) & (data['date/time'].dt.date <= end_date)] |
|
|
| st.markdown(f"Tổng số va chạm trong khoảng thời gian: **{len(filtered_data)}**") |
|
|
| if not filtered_data.empty: |
| midpoint = (np.average(filtered_data['latitude']), np.average(filtered_data['longitude'])) |
|
|
| m = folium.Map(location=midpoint, tiles='OpenStreetMap', zoom_start=11, control_scale=True) |
|
|
| mc = MarkerCluster() |
| for idx, row in filtered_data.iterrows(): |
| mc.add_child(folium.Marker(location=[row['latitude'], row['longitude']])) |
| m.add_child(mc) |
|
|
| st_folium(m, width=700, height=500) |
| else: |
| st.write("Không có dữ liệu tai nạn trong khoảng thời gian bạn chọn.") |
|
|
| |
|
|
| st.header("Biểu đồ thống kê tai nạn giao thông") |
|
|
| data['date'] = data['date/time'].dt.date |
| if 'borough' in data.columns: |
| data['borough'] = data['borough'].astype(str).str.upper() |
| else: |
| data['borough'] = 'UNKNOWN' |
|
|
| boroughs = ['QUEENS', 'BROOKLYN', 'MANHATTAN', 'BRONX', 'STATEN ISLAND'] |
|
|
| |
| data['month'] = data['date/time'].dt.month |
| by_month = data.groupby('month')[['number of persons injured', 'number of persons killed']].sum().reset_index() |
| by_month['month_name'] = by_month['month'].apply(lambda x: calendar.month_name[x]) |
|
|
| chart_option = st.selectbox("Chọn biểu đồ muốn xem:", [ |
| "Số người bị thương và tử vong theo ngày và quận", |
| "Số vụ tai nạn trong 365 ngày gần nhất theo quận", |
| "Tổng số người bị thương và tử vong theo năm", |
| "Số người bị thương và tử vong theo loại nạn nhân (Người đi bộ, Xe đạp, Người lái xe)", |
| "Số người bị thương và tử vong theo tháng" |
| ]) |
|
|
| if chart_option == "Số người bị thương và tử vong theo ngày và borough": |
| grouped = data.groupby(['date', 'borough'])[['number of persons injured', 'number of persons killed']].sum().reset_index() |
| fig = make_subplots(rows=2, cols=1, subplot_titles=('Số người bị thương mỗi ngày', 'Số người tử vong mỗi ngày')) |
| for bor in boroughs: |
| df_bor = grouped[grouped['borough'] == bor] |
| fig.add_trace(go.Scatter(x=df_bor['date'], y=df_bor['number of persons injured'], name=bor), row=1, col=1) |
| fig.add_trace(go.Scatter(x=df_bor['date'], y=df_bor['number of persons killed'], name=bor), row=2, col=1) |
| fig.update_layout(height=700, template='plotly_dark') |
| st.plotly_chart(fig, use_container_width=True) |
|
|
| elif chart_option == "Số vụ tai nạn trong 365 ngày gần nhất theo borough": |
| recent_data = data[data['date'] >= (data['date'].max() - pd.Timedelta(days=365))] |
| feat_cols = ['number of persons injured', 'number of persons killed'] |
| fig = make_subplots(rows=2, cols=1, subplot_titles=('Số người bị thương mỗi ngày (365 ngày gần nhất)', 'Số người tử vong mỗi ngày (365 ngày gần nhất)')) |
| for bor in boroughs: |
| df_bor = recent_data[recent_data['borough'] == bor] |
| df_grouped = df_bor.groupby('date')[feat_cols].sum() |
| fig.add_trace(go.Scatter(x=df_grouped.index, y=df_grouped['number of persons injured'], name=bor), row=1, col=1) |
| fig.add_trace(go.Scatter(x=df_grouped.index, y=df_grouped['number of persons killed'], name=bor), row=2, col=1) |
| fig.update_layout(height=700, template='plotly_dark') |
| st.plotly_chart(fig, use_container_width=True) |
|
|
| elif chart_option == "Tổng số người bị thương và tử vong theo năm": |
| data['year'] = data['date/time'].dt.year |
| by_year = data.groupby('year')[['number of persons injured', 'number of persons killed']].sum().reset_index() |
| fig = make_subplots(rows=1, cols=2, subplot_titles=('Tổng số người bị thương theo năm', 'Tổng số người tử vong theo năm')) |
| fig.add_trace(go.Bar(x=by_year['year'], y=by_year['number of persons injured'], name='Bị thương'), row=1, col=1) |
| fig.add_trace(go.Bar(x=by_year['year'], y=by_year['number of persons killed'], name='Tử vong'), row=1, col=2) |
| fig.update_layout(height=400, template='plotly_dark') |
| st.plotly_chart(fig, use_container_width=True) |
|
|
| elif chart_option == "Số người bị thương và tử vong theo loại nạn nhân (Người đi bộ, Xe đạp, Người lái xe)": |
| inj_cols = ['number of pedestrians injured', 'number of cyclist injured', 'number of motorist injured'] |
| kill_cols = ['number of pedestrians killed', 'number of cyclist killed', 'number of motorist killed'] |
| labels = ['Người đi bộ', 'Xe đạp', 'Người lái xe'] |
|
|
| fig = make_subplots(rows=3, cols=1, subplot_titles=labels) |
| for i, (inj_col, kill_col) in enumerate(zip(inj_cols, kill_cols)): |
| daily_inj = data.groupby('date')[inj_col].sum() |
| daily_kill = data.groupby('date')[kill_col].sum() |
| fig.add_trace(go.Scatter(x=daily_inj.index, y=daily_inj.values, name='Bị thương'), row=i+1, col=1) |
| fig.add_trace(go.Scatter(x=daily_kill.index, y=daily_kill.values, name='Tử vong'), row=i+1, col=1) |
| fig.update_layout(height=900, template='plotly_dark') |
| st.plotly_chart(fig, use_container_width=True) |
|
|
| elif chart_option == "Số người bị thương và tử vong theo tháng": |
| fig = make_subplots(rows=1, cols=2, subplot_titles=('Số người bị thương theo tháng', 'Số người tử vong theo tháng')) |
| |
| fig.add_trace(go.Bar(x=by_month['month_name'], y=by_month['number of persons injured'], name='Bị thương'), row=1, col=1) |
| fig.add_trace(go.Bar(x=by_month['month_name'], y=by_month['number of persons killed'], name='Tử vong'), row=1, col=2) |
| |
| fig.update_layout(template='plotly_dark', width=900, height=450) |
| st.plotly_chart(fig, use_container_width=True) |
|
|