File size: 5,276 Bytes
df2b5a3
 
8b4e4f2
df2b5a3
 
8b4e4f2
 
df2b5a3
 
8b4e4f2
 
df2b5a3
 
8b4e4f2
df2b5a3
 
 
 
 
 
 
8b4e4f2
 
 
df2b5a3
8b4e4f2
 
 
 
 
df2b5a3
8b4e4f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df2b5a3
8b4e4f2
 
 
 
 
df2b5a3
8b4e4f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df2b5a3
 
8b4e4f2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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.")