ralate2's picture
Update app.py
8b4e4f2 verified
import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
# Streamlit page setup
st.set_page_config(page_title="Legislative Bill Analysis", layout="wide")
st.title("Legislative Bill Analysis Dashboard")
# File uploader
uploaded_file = st.file_uploader("Upload Illinois_Entire_Data_Insights_Final_v2.csv", type=["csv", "xlsx"])
if uploaded_file:
# Read file
if uploaded_file.name.endswith('.csv'):
df = pd.read_csv(uploaded_file)
else:
df = pd.read_excel(uploaded_file)
st.success("File uploaded and read successfully!")
# Preprocessing date and year
df['status_date'] = pd.to_datetime(df['status_date'], errors='coerce')
df['year'] = df['status_date'].dt.year
# ------------------------
# Visualization 1: Yearly Bills by Intent
# ------------------------
st.header(" Bills Over Time by Intent")
yearly_intent_counts = df.groupby(['year', 'intent_standardized']).size().reset_index(name='bill_count')
fig1 = px.bar(
yearly_intent_counts,
x='year',
y='bill_count',
color='intent_standardized',
title='Bills Over Time by Intent',
labels={'year': 'Year', 'bill_count': 'Number of Bills', 'intent_standardized': 'Intent'},
barmode='group',
height=500,
color_discrete_sequence=px.colors.qualitative.Set2
)
fig1.update_layout(
xaxis=dict(tickangle=0),
legend_title_text='Intent',
plot_bgcolor='white',
paper_bgcolor='white',
font=dict(color='black'),
title_font=dict(size=20)
)
st.plotly_chart(fig1, use_container_width=True)
# ------------------------
# Visualization 2: Animated Stance Distribution by Policy Area
# ------------------------
st.header("Stance Distribution Across Policy Areas (Animated by Year)")
grouped = df.groupby(['year', 'policy_impact_areas_standardized', 'stance_standardized']).size().reset_index(name='count')
fig2 = px.bar(
grouped,
x='count',
y='policy_impact_areas_standardized',
color='stance_standardized',
orientation='h',
animation_frame='year',
title='Stance Distribution Across Policy Areas (Animated by Year)',
labels={
'count': 'Number of Bills',
'policy_impact_areas_standardized': 'Policy Area',
'stance_standardized': 'Stance'
},
height=600,
color_discrete_sequence=px.colors.qualitative.Set2
)
fig2.update_layout(
legend_title='Stance',
xaxis_title='Number of Bills',
yaxis_title='Policy Area',
plot_bgcolor='white',
paper_bgcolor='white',
font=dict(color='black'),
title_font=dict(size=20),
margin=dict(t=60, l=150)
)
st.plotly_chart(fig2, use_container_width=True)
# ------------------------
# Visualization 3: Sankey Diagram - Intent β†’ Beneficiaries β†’ Increasing Aspects
# ------------------------
st.header("πŸ”— Top Intent β†’ Beneficiaries β†’ Increasing Aspect Flows (Sankey)")
def shorten(text, max_len=35):
return text if len(text) <= max_len else text[:max_len] + "..."
sankey_data = df[['intent_standardized', 'intended_beneficiaries_standardized', 'increasing_aspects_standardized']].dropna()
path_counts = (
sankey_data.groupby(['intent_standardized', 'intended_beneficiaries_standardized', 'increasing_aspects_standardized'])
.size()
.reset_index(name='count')
.sort_values(by='count', ascending=False)
)
TOP_N = 15
filtered_paths = path_counts.head(TOP_N)
unique_labels = pd.unique(filtered_paths[['intent_standardized', 'intended_beneficiaries_standardized', 'increasing_aspects_standardized']].values.ravel())
short_labels = [shorten(label) for label in unique_labels]
label_to_index = {label: i for i, label in enumerate(unique_labels)}
label_to_short = dict(zip(unique_labels, short_labels))
sources = list(filtered_paths['intent_standardized'].map(label_to_index))
targets = list(filtered_paths['intended_beneficiaries_standardized'].map(label_to_index))
values = list(filtered_paths['count'])
sources += list(filtered_paths['intended_beneficiaries_standardized'].map(label_to_index))
targets += list(filtered_paths['increasing_aspects_standardized'].map(label_to_index))
values += list(filtered_paths['count'])
fig3 = go.Figure(data=[go.Sankey(
arrangement="snap",
node=dict(
pad=25,
thickness=20,
line=dict(color="black", width=0.3),
label=[label_to_short[label] for label in unique_labels],
color="lightsteelblue"
),
link=dict(
source=sources,
target=targets,
value=values,
color="rgba(150,150,150,0.4)"
)
)])
fig3.update_layout(
title_text="Top Intent β†’ Beneficiaries β†’ Increasing Aspect Flows",
font_size=12,
height=600,
margin=dict(l=50, r=50, t=80, b=30)
)
st.plotly_chart(fig3, use_container_width=True)
else:
st.info(" Please upload a dataset file to view the visualizations.")