ebader commited on
Commit
e985fcd
·
verified ·
1 Parent(s): 47289b9

Create streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +178 -0
streamlit_app.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ !pip install "altair[all]==5.5.0"
2
+ import streamlit as st
3
+ import pandas as pd
4
+ import altair as alt
5
+ from vega_datasets import data
6
+ import us
7
+
8
+
9
+
10
+
11
+ # -------------------------------------------------
12
+ # PAGE CONFIG + TITLE
13
+ # -------------------------------------------------
14
+ st.set_page_config(page_title="University Donor Dashboard", layout="wide")
15
+ st.title("University Donor Dashboard")
16
+ alt.data_transformers.enable("default", max_rows=None)
17
+
18
+ # -------------------------------------------------
19
+ # DATA
20
+ # -------------------------------------------------
21
+ @st.cache_data
22
+ def load_data():
23
+ df = pd.read_csv("university-donations.csv")
24
+ df["Gift Date"] = pd.to_datetime(
25
+ df["Gift Date"],
26
+ format="%m/%d/%y",
27
+ errors="coerce"
28
+ )
29
+ df["Year"] = df["Gift Date"].dt.year.astype("Int64")
30
+ df["YearMonth"] = df["Gift Date"].dt.to_period("M").astype(str)
31
+
32
+ # 2-letter state → FIPS
33
+ state_id = {s.abbr: int(s.fips) for s in us.states.STATES}
34
+ df["state_fips"] = df["State"].map(state_id)
35
+ return df
36
+
37
+ df = load_data()
38
+ st.write("Loaded rows:", len(df)) # quick sanity check
39
+
40
+ # -------------------------------------------------
41
+ # SIDEBAR FILTERS
42
+ # -------------------------------------------------
43
+ st.sidebar.header("Filters")
44
+ col_opts = ["All"] + sorted(df["College"].dropna().unique())
45
+ mot_opts = ["All"] + sorted(df["Gift Allocation"].dropna().unique())
46
+
47
+ col_pick = st.sidebar.selectbox("College", col_opts, index=0)
48
+ mot_pick = st.sidebar.selectbox("Motivation (Gift Allocation)", mot_opts, index=0)
49
+
50
+ st.sidebar.write(f"Selected College: {col_pick}")
51
+ st.sidebar.write(f"Selected Motivation: {mot_pick}")
52
+
53
+ mask = pd.Series(True, index=df.index)
54
+ if col_pick != "All":
55
+ mask &= df["College"] == col_pick
56
+ if mot_pick != "All":
57
+ mask &= df["Gift Allocation"] == mot_pick
58
+ df_filt = df[mask]
59
+
60
+ # Check if the filtered dataframe is empty
61
+ if df_filt.empty:
62
+ st.warning("No data matches the selected filters.")
63
+ else:
64
+ # -------------------------------------------------
65
+ # SELECTIONS (empty="all" to show all data initially)
66
+ # -------------------------------------------------
67
+ state_select = alt.selection_point(fields=["state_fips"], toggle=False, empty="all")
68
+ brush = alt.selection_interval(encodings=["x"], empty="all")
69
+ subcategory_select = alt.selection_point(
70
+ fields=["Allocation Subcategory"],
71
+ toggle="event.shiftKey",
72
+ empty="all"
73
+ )
74
+
75
+ # -------------------------------------------------
76
+ # CHOROPLETH MAP
77
+ # -------------------------------------------------
78
+
79
+ state_totals = (
80
+ df_filt.groupby("state_fips", as_index=False)
81
+ .agg(Gift_Amount_sum=("Gift Amount", "sum"),
82
+ Gift_Count=("Gift Amount", "count"))
83
+ )
84
+
85
+
86
+ states = alt.topo_feature(data.us_10m.url, "states")
87
+ map_chart = (
88
+ alt.Chart(states)
89
+ .mark_geoshape(stroke="white", strokeWidth=0.5)
90
+ .encode(
91
+ color=alt.condition(
92
+ state_select,
93
+ alt.Color("Gift_Amount_sum:Q",
94
+ scale=alt.Scale(scheme="blues"),
95
+ title="Total Gifts ($)"),
96
+ alt.value("lightgray")
97
+ ),
98
+ tooltip=[
99
+ alt.Tooltip("Gift_Amount_sum:Q", title="Total Gifts ($)", format=",.0f"),
100
+ alt.Tooltip("Gift_Count:Q", title="# Gifts")
101
+ ]
102
+ )
103
+ .transform_lookup(
104
+ lookup="id",
105
+ from_=alt.LookupData(state_totals,
106
+ key="state_fips",
107
+ fields=["Gift_Amount_sum", "Gift_Count"])
108
+ )
109
+ .add_params(state_select)
110
+ .project(type="albersUsa")
111
+ .properties(width=380, height=250)
112
+ )
113
+
114
+ # -------------------------------------------------
115
+ # LINE – GIFTS BY YEAR
116
+ # -------------------------------------------------
117
+ line_chart = (
118
+ alt.Chart(df_filt)
119
+ .transform_filter(state_select)
120
+ .mark_line(point=True)
121
+ .encode(
122
+ x=alt.X("Year:O", sort="ascending"),
123
+ y=alt.Y("sum(Gift Amount):Q", title="Total Gifts ($)"),
124
+ tooltip=[
125
+ alt.Tooltip("Year:O", title="Year"),
126
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f")
127
+ ]
128
+ )
129
+ .add_params(state_select, brush)
130
+ .properties(width=380, height=250)
131
+ )
132
+
133
+ # -------------------------------------------------
134
+ # BAR – TOTAL BY COLLEGE
135
+ # -------------------------------------------------
136
+ bar_college = (
137
+ alt.Chart(df_filt)
138
+ .transform_filter(state_select)
139
+ .mark_bar()
140
+ .encode(
141
+ y=alt.Y("College:N", sort="-x", title="College"),
142
+ x=alt.X("sum(Gift Amount):Q", title="Total Gifts ($)"),
143
+ tooltip=[
144
+ alt.Tooltip("College:N", title="College"),
145
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f")
146
+ ]
147
+ )
148
+ .add_params(state_select)
149
+ .properties(width=380, height=400)
150
+ )
151
+
152
+ # -------------------------------------------------
153
+ # BAR – TOTAL BY SUB-CATEGORY
154
+ # -------------------------------------------------
155
+ bar_sub = (
156
+ alt.Chart(df_filt)
157
+ .transform_filter(state_select)
158
+ .transform_filter(brush)
159
+ .mark_bar()
160
+ .encode(
161
+ y=alt.Y("Allocation Subcategory:N", sort="-x", title="Allocation Sub-category"),
162
+ x=alt.X("sum(Gift Amount):Q", title="Total Gifts ($)"),
163
+ color=alt.condition(subcategory_select, alt.value("#1f77b4"), alt.value("lightgray")),
164
+ tooltip=[
165
+ alt.Tooltip("Allocation Subcategory:N", title="Sub-category"),
166
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f")
167
+ ]
168
+ )
169
+ .add_params(state_select, brush, subcategory_select)
170
+ .properties(width=380, height=400)
171
+ )
172
+
173
+ # -------------------------------------------------
174
+ # LAYOUT
175
+ # -------------------------------------------------
176
+ upper = alt.hconcat(map_chart, line_chart).resolve_scale(color="independent")
177
+ lower = alt.hconcat(bar_college, bar_sub)
178
+ st.altair_chart(alt.vconcat(upper, lower), use_container_width=True)