import numpy as np
import pandas as pd
import plotly.express as px
import dash
import dash_bootstrap_components as dbc
from dash import Dash, html, dcc, Input, Output, State
df = pd.read_csv("all_outlays_2025-02-14.csv", parse_dates=['Date'])
df['pct_change'] = df['Daily'].pct_change()
df['pct_change'] = df['pct_change'].replace([np.inf, -np.inf], np.nan)
df['pct_change'] = df['pct_change'].fillna(0)
pivot_df = (
df.pivot_table(
index=["Date"],
columns="transaction_catg_renamed",
values="Daily",
aggfunc="sum"
)
.fillna(0)
)
pivot_pct_df = (
df.pivot_table(
index=["Date"],
columns="transaction_catg_renamed",
values="pct_change",
)
.fillna(0)
)
categories = df['transaction_catg_renamed'].unique()
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.UNITED])
app.title = "US federal government’s expenditure"
sidebar = dbc.Col([
html.Hr(),
html.H6("Selecting Time Frequency"),
dbc.RadioItems(
id="period-filter",
options=[
{'label': 'Days', 'value': 'D'},
{'label': 'Weeks', 'value': 'W'},
{'label': 'Months', 'value': 'ME'},
{'label': 'Quarters', 'value': 'QE'}
],
value='ME',
inline=False,
class_name="btn btn-info",
),
html.Hr(),
html.H6("Transaction Categories"),
html.Hr(),
dbc.Button("Select Categories", id="open-modal", n_clicks=0, className="btn btn-info"),
dbc.Modal([
dbc.ModalHeader("Select Categories"),
dbc.ModalBody(dbc.Checklist(
id='category-checklist',
options=[{'label': cat, 'value': cat} for cat in categories],
value= ['IAP - USAID',
'Dept of Education (ED)',
'Dept of Commerce (DOC)',
'Dept of Energy (DOE)',
'Dept of Justice (DOJ)'],
inline=False,
switch=True,
style={"backgroundColor": "#f0f0f0", "padding": "8px", "fontSize": "16px"}
)),
dbc.ModalFooter(
dbc.Button("Close", id="close-modal", className="btn btn-info"
)
)
], id="modal", is_open=False),
html.Div(id="selected-categories", style={"marginTop": "10px"})
], width=3, style={'background-color': '#f8f9fa', 'padding': '20px', 'text-align': 'center', 'position': 'fixed',
'height': '100vh',
'overflow': 'auto'})
content = dbc.Col([
html.H4("The Hamilton Project: Tracking US federal expenditure since 2022",
style={"text-align": "center"}),
html.Hr(),
dbc.Row([
html.H5("Total US Federal Spending Trends by Category",
style={"backgroundColor": "#f0f0f0", "padding": "8px", "text-align": "center"}),
dbc.Col(dcc.Graph(id="area-chart"), width=12),
]),
dbc.Row([
html.H5("Percentage Change in US Federal Expenditure by Category",
style={"backgroundColor": "#f0f0f0", "padding": "8px", "text-align": "center"}),
dbc.Col(dcc.Graph(id="line-chart"), width=12),
]),
], width={"size": 9, "offset": 3})
app.layout = dbc.Container([
dbc.Row([
sidebar,
content
])
], fluid=True)
@app.callback(
Output("modal", "is_open"),
[Input("open-modal", "n_clicks"), Input("close-modal", "n_clicks")],
[State("modal", "is_open")],
)
def toggle_modal(n1, n2, is_open):
if n1 or n2:
return not is_open
return is_open
@app.callback(
Output("selected-categories", "children"),
Input('category-checklist', 'value')
)
def display_selected_categories(selected_categories):
return f"Selected Categories: {', '.join(selected_categories)}" if selected_categories else "No categories selected"
@app.callback(
Output("area-chart", "figure"),
Output("line-chart", "figure"),
Input("period-filter", "value"),
Input('category-checklist', 'value')
)
def update_charts(selected_period, selected_categories):
resample_str = selected_period
filtered_pivot_df = pivot_df[selected_categories]
filtered_pivot_pct_df = pivot_pct_df[selected_categories]
resampled_pivot_df = filtered_pivot_df.resample(resample_str).sum()
resampled_pivot_pct_df = filtered_pivot_pct_df.resample(resample_str).mean()
fig_area = px.area(resampled_pivot_df, template='presentation', color_discrete_sequence=px.colors.qualitative.Prism,
labels={'transaction_catg_renamed': 'Transaction Categories', 'Date': '', 'value': 'US$ in Billions'},
markers=True)
fig_area.update_layout(legend=dict(title=None, orientation="h", y=1, yanchor="bottom", x=0.5, xanchor="center",
font=dict(size=16)))
fig_line = px.line(resampled_pivot_pct_df, template='presentation', color_discrete_sequence=px.colors.qualitative.Prism,
labels={'transaction_catg_renamed': 'Transaction Categories', 'Date': '', 'value': 'Percentage Change %'},
markers=True)
fig_line.update_layout(showlegend=False)
return fig_area, fig_line