ebader commited on
Commit
63c11c3
·
verified ·
1 Parent(s): 118633a

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +138 -0
  2. requirements.txt +4 -2
  3. university-donations.csv +0 -0
app.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ########################
2
+ # app.py – Streamlit #
3
+ ########################
4
+ import streamlit as st
5
+ import pandas as pd
6
+ import altair as alt
7
+ from vega_datasets import data
8
+ import us
9
+
10
+ st.set_page_config(page_title="University Donor Dashboard",
11
+ layout="wide")
12
+
13
+ # ---------- DATA ----------
14
+ @st.cache_data
15
+ def load_data():
16
+ # Make sure the CSV is in the same folder as app.py
17
+ df = pd.read_csv("university-donations.csv")
18
+ df["Gift Date"] = pd.to_datetime(df["Gift Date"])
19
+ df["Year"] = df["Gift Date"].dt.year
20
+ df["YearMonth"] = df["Gift Date"].dt.to_period("M").astype(str)
21
+
22
+ # map 2-letter state → FIPS id for topojson join
23
+ state_id = {s.abbr: int(s.fips) for s in us.states.STATES}
24
+ df["state_fips"] = df["State"].map(state_id)
25
+ return df
26
+
27
+ df = load_data()
28
+ alt.data_transformers.enable("default", max_rows=None)
29
+
30
+ # ---------- SIDEBAR FILTERS ----------
31
+ st.sidebar.header("Filters")
32
+ col_opts = ["All"] + sorted(df["College"].unique())
33
+ mot_opts = ["All"] + sorted(df["Gift Allocation"].unique())
34
+
35
+ col_pick = st.sidebar.selectbox("College", col_opts, index=0)
36
+ mot_pick = st.sidebar.selectbox("Motivation (Gift Allocation)", mot_opts, index=0)
37
+
38
+ mask = pd.Series([True] * len(df))
39
+ if col_pick != "All":
40
+ mask &= df["College"] == col_pick
41
+ if mot_pick != "All":
42
+ mask &= df["Gift Allocation"] == mot_pick
43
+ df_filt = df[mask]
44
+
45
+ # ---------- ALTAIR SELECTIONS ----------
46
+ state_select = alt.selection_point(fields=["state_fips"], toggle=False, empty="all")
47
+ brush = alt.selection_interval(encodings=["x"])
48
+ subcategory_select = alt.selection_point(fields=["Allocation Subcategory"],
49
+ toggle="event", empty="all")
50
+
51
+ # ---------- CHOROPLETH MAP ----------
52
+ states = alt.topo_feature(data.us_10m.url, "states")
53
+ map_chart = (
54
+ alt.Chart(states)
55
+ .mark_geoshape(stroke="white", strokeWidth=0.5)
56
+ .encode(
57
+ color=alt.condition(
58
+ state_select,
59
+ alt.Color("sum(Gift Amount):Q",
60
+ scale=alt.Scale(scheme="blues"),
61
+ title="Total Gifts ($)"),
62
+ alt.value("lightgray")
63
+ ),
64
+ tooltip=[
65
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f"),
66
+ alt.Tooltip("count():Q", title="# Gifts")
67
+ ]
68
+ )
69
+ .transform_lookup(
70
+ lookup="id",
71
+ from_=alt.LookupData(df_filt,
72
+ key="state_fips",
73
+ fields=["Gift Amount"])
74
+ )
75
+ .add_params(state_select)
76
+ .project(type="albersUsa")
77
+ .properties(width=380, height=250)
78
+ )
79
+
80
+ # ---------- LINE: GIFTS BY YEAR ----------
81
+ line_chart = (
82
+ alt.Chart(df_filt)
83
+ .transform_filter(state_select)
84
+ .mark_line(point=True)
85
+ .encode(
86
+ x=alt.X("Year:O", sort="ascending"),
87
+ y=alt.Y("sum(Gift Amount):Q", title="Total Gifts ($)"),
88
+ tooltip=[
89
+ alt.Tooltip("Year:O", title="Year"),
90
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f")
91
+ ]
92
+ )
93
+ .add_params(brush)
94
+ .properties(width=380, height=250)
95
+ )
96
+
97
+ # ---------- BAR: TOTAL BY COLLEGE ----------
98
+ bar_college = (
99
+ alt.Chart(df_filt)
100
+ .transform_filter(state_select)
101
+ .mark_bar()
102
+ .encode(
103
+ y=alt.Y("College:N", sort="-x", title="College"),
104
+ x=alt.X("sum(Gift Amount):Q", title="Total Gifts ($)"),
105
+ tooltip=[
106
+ alt.Tooltip("College:N", title="College"),
107
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f")
108
+ ]
109
+ )
110
+ .properties(width=380, height=400)
111
+ )
112
+
113
+ # ---------- BAR: TOTAL BY SUB-CATEGORY ----------
114
+ bar_sub = (
115
+ alt.Chart(df_filt)
116
+ .transform_filter(state_select)
117
+ .transform_filter(brush)
118
+ .mark_bar()
119
+ .encode(
120
+ y=alt.Y("Allocation Subcategory:N", sort="-x",
121
+ title="Allocation Sub-category"),
122
+ x=alt.X("sum(Gift Amount):Q", title="Total Gifts ($)"),
123
+ color=alt.condition(
124
+ subcategory_select, alt.value("#1f77b4"), alt.value("lightgray")
125
+ ),
126
+ tooltip=[
127
+ alt.Tooltip("Allocation Subcategory:N", title="Sub-category"),
128
+ alt.Tooltip("sum(Gift Amount):Q", title="Total Gifts ($)", format=",.0f")
129
+ ]
130
+ )
131
+ .add_params(subcategory_select)
132
+ .properties(width=380, height=400)
133
+ )
134
+
135
+ # ---------- LAYOUT ----------
136
+ upper = alt.hconcat(map_chart, line_chart).resolve_scale(color="independent")
137
+ lower = alt.hconcat(bar_college, bar_sub)
138
+ st.altair_chart(alt.vconcat(upper, lower), use_container_width=True)
requirements.txt CHANGED
@@ -1,3 +1,5 @@
1
- altair
2
  pandas
3
- streamlit
 
 
 
1
+ streamlit==1.35.0
2
  pandas
3
+ altair==5.3.0
4
+ vega_datasets
5
+ us
university-donations.csv ADDED
The diff for this file is too large to render. See raw diff