Cool project this week. Didn’t know about this organization before today. I enjoy coming across organizations and resources that are out there illustrating and analyzing gov spend, ill continue to review more of their resources!
I created a dash app with side nav bar. Users can click into the analysis they want by the nav links in the side bar.
Provided a homepage that briefly describes what the dash app ( Welcome to the Spend Tracker Dashboard) - very general info
The First link is a bar animation of the spend (aggregate by month) an category (billions).
Then followed by some other plotly illustrations
import dash
from dash import dcc, html, Input, Output
import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import uuid
# -------------------------
# Data & Figure Preparation
# -------------------------
print("Script started. Reading CSV...")
csv_path = r'path.csv'
try:
df = pd.read_csv(csv_path, parse_dates=['Date'])
print("CSV read successfully.")
except Exception as e:
print("Error reading CSV:", e)
raise
# Rename columns for consistency
df.rename(columns={'Date': 'date', '7-day moving average': 'moving_avg'}, inplace=True)
# Exclude rows with 'total' in the category name (if any)
df = df[~df['transaction_catg_renamed'].str.contains('total', case=False, na=False)]
# Create an abbreviated category column (up to 15 characters)
df['cat_abbrev'] = df['transaction_catg_renamed'].apply(
lambda x: x if len(x) <= 15 else x[:12] + "..."
)
# Keep the full category name for hover text (will use the first encountered value per group)
df['full_cat'] = df['transaction_catg_renamed']
# Create a 'month' column representing the start of each month
df['month'] = df['date'].dt.to_period('M').apply(lambda r: r.start_time)
# -------------------------
# Animated Bar Chart (Top 20 Categories - Aggregate Spending)
# -------------------------
# Group by month and category, summing the 'Daily' spending and keeping the full category name
df_monthly = (
df.groupby(['month', 'cat_abbrev'], as_index=False)
.agg({'Daily': 'sum', 'full_cat': 'first'})
)
# For each month, get the top 20 categories by total aggregate spending
df_monthly_top20 = (
df_monthly.sort_values(['month', 'Daily'], ascending=[True, False])
.groupby('month')
.head(20)
.reset_index(drop=True)
)
df_monthly_top20['month_str'] = df_monthly_top20['month'].dt.strftime('%Y-%m')
bar_fig = px.bar(
df_monthly_top20,
x="Daily",
y="cat_abbrev",
orientation='h',
animation_frame="month_str",
color="cat_abbrev",
range_x=[0, df_monthly_top20["Daily"].max() * 1.2],
labels={"cat_abbrev": "Category", "Daily": "Total Aggregate Spending (Billions)"},
title="Animated Top 20 Monthly Aggregate Spending by Category",
custom_data=["full_cat"]
)
bar_fig.update_traces(
hovertemplate='<b>%{customdata[0]}</b><br>Total Aggregate Spending: %{x} Billion<br><extra></extra>'
)
bar_fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 1000
bar_fig.layout.updatemenus[0].buttons[0].args[1]['transition']['duration'] = 3
bar_fig.update_layout(margin=dict(l=150, r=20, t=50, b=50))
# -------------------------
# Line Chart (Total Monthly Spending)
# -------------------------
df['Daily'] = pd.to_numeric(df['Daily'], errors='coerce')
df_monthly_total = df.groupby(df['month'].dt.strftime('%Y-%m'))['Daily'].sum().reset_index()
line_fig = px.line(
df_monthly_total,
x="month",
y="Daily",
title="Total Monthly Spending Across All Categories",
labels={"month": "Month", "Daily": "Total Spending (Billions)"},
markers=True
)
line_fig.update_traces(line=dict(width=3), marker=dict(size=8))
# -------------------------
# Pie Chart (Top Categories + "Other")
# -------------------------
latest_month = df['month'].max()
df_latest_month = df[df['month'] == latest_month]
df_latest_month_grouped = df_latest_month.groupby('cat_abbrev', as_index=False)['Daily'].sum()
df_latest_month_grouped = df_latest_month_grouped.sort_values('Daily', ascending=False)
top_n = 10
df_top = df_latest_month_grouped.head(top_n)
df_other = df_latest_month_grouped.iloc[top_n:]
df_other_sum = df_other['Daily'].sum()
df_top.loc[len(df_top)] = ['Other', df_other_sum]
pie_fig = px.pie(
df_top,
names="cat_abbrev",
values="Daily",
title=f"Spending Distribution by Category ({latest_month.strftime('%Y-%m')})",
)
pie_fig.update_traces(textinfo="label+percent", pull=[0.1 if i < top_n else 0 for i in range(len(df_top))])
# -------------------------
# Sankey Diagram (Spending Flow)
# -------------------------
top_n = 10
df_sankey = df.groupby('cat_abbrev', as_index=False)['Daily'].sum().sort_values('Daily', ascending=False)
df_top = df_sankey.head(top_n)
df_other_sum = df_sankey.iloc[top_n:]['Daily'].sum()
df_top.loc[len(df_top)] = ['Other', df_other_sum]
node_labels = ["All Outlays"] + df_top['cat_abbrev'].tolist()
source = [0] * len(df_top)
target = list(range(1, len(df_top) + 1))
values = df_top["Daily"].tolist()
sankey_fig = go.Figure(data=[go.Sankey(
node=dict(pad=15, thickness=20, label=node_labels),
link=dict(source=source, target=target, value=values)
)])
sankey_fig.update_layout(title=f"Sankey Diagram of Total Spending Flow (Top {top_n} + Other)")
# -------------------------
# Treemap Chart (Aggregate Spend by Category)
# -------------------------
df_treemap = df.groupby('cat_abbrev', as_index=False)['Daily'].sum()
treemap_fig = px.treemap(
df_treemap,
path=['cat_abbrev'],
values='Daily',
title="Treemap of Total Aggregate Spend by Category"
)
treemap_fig.update_traces(textinfo="label+value+percent entry")
# -------------------------
# Layout & Navigation
# -------------------------
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
# Sidebar
html.Div([
html.H2("Spend Dashboard", style={"color": "white"}),
html.Hr(style={"borderColor": "white"}),
dbc.Nav([
dbc.NavLink("Home", href="/home", active="exact"),
dbc.NavLink("Animated Bar Chart", href="/bar-chart", active="exact"),
dbc.NavLink("Line Chart", href="/line-chart", active="exact"),
dbc.NavLink("Pie Chart", href="/pie-chart", active="exact"),
dbc.NavLink("Sankey Diagram", href="/sankey", active="exact"),
dbc.NavLink("Treemap", href="/treemap", active="exact"),
], vertical=True, pills=True)
], style={"width": "16rem", "position": "fixed", "height": "100vh", "background-color": "#355E3B", "padding": "1rem", "color": "white"}),
# Content
html.Div(id='page-content', style={"margin-left": "18rem", "padding": "2rem"})
])
# -------------------------
# Homepage Layout
# -------------------------
def homepage_layout():
return html.Div([
html.H1("Welcome to the Spend Tracker Dashboard", style={'textAlign': 'center'}),
html.P(
"This dashboard provides insights into monthly spending patterns across various categories. "
"Explore interactive visualizations to gain a deeper understanding of spending trends over time.",
style={'textAlign': 'center', 'fontSize': '18px'}
),
html.Hr(),
html.Div([
html.H3("Navigation Guide:"),
html.Ul([
html.Li([html.B("Animated Bar Chart:"), " Visualize monthly changes in the top 20 spending categories with an animated bar chart showing aggregate spend."]),
html.Li([html.B("Line Chart:"), " Explore the overall monthly spending trends with a clear line chart."]),
html.Li([html.B("Pie Chart:"), " Understand the spending distribution for the latest month with a pie chart."]),
html.Li([html.B("Sankey Diagram:"), " See the spending flow for top categories plus an 'Other' category using a Sankey diagram."]),
html.Li([html.B("Treemap:"), " View a treemap of the total aggregate spend by category."]),
], style={'fontSize': '16px'}),
html.P("Select a chart from the sidebar to get started.", style={'fontSize': '16px'}),
], style={'maxWidth': '600px', 'margin': '0 auto'}),
], style={'padding': '2rem'})
# -------------------------
# Page Switching Callback
# -------------------------
@app.callback(Output('page-content', 'children'), [Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/bar-chart':
graph_id = f'bar-chart-graph-{uuid.uuid4()}'
return dcc.Graph(id=graph_id, figure=bar_fig)
elif pathname == '/line-chart':
graph_id = f'line-chart-graph-{uuid.uuid4()}'
return dcc.Graph(id=graph_id, figure=line_fig)
elif pathname == '/pie-chart':
graph_id = f'pie-chart-graph-{uuid.uuid4()}'
return dcc.Graph(id=graph_id, figure=pie_fig)
elif pathname == '/sankey':
graph_id = f'sankey-graph-{uuid.uuid4()}'
return dcc.Graph(id=graph_id, figure=sankey_fig)
elif pathname == '/treemap':
graph_id = f'treemap-graph-{uuid.uuid4()}'
return dcc.Graph(id=graph_id, figure=treemap_fig)
elif pathname in ['/home', '/']:
return homepage_layout()
else:
return html.Div([
html.H3("404: Page not found"),
html.P("The page you are looking for does not exist.")
])
# -------------------------
# Run App
# -------------------------
if __name__ == "__main__":
print("Starting Dash server on http://127.0.0.1:8050 ...")
app.run_server(debug=False)