import dash
from dash import Dash, dcc, html
import dash_bootstrap_components as dbc
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output
df = pd.read_csv('https://raw.githubusercontent.com/plotly/Figure-Friday/refs/heads/main/2025/week-12/banknotesData.csv')
app = Dash(__name__, external_stylesheets=[dbc.themes.FLATLY])
# Function to generate treemap
def country_currency_representation(df, selected_country, selected_gender, selected_profession, selected_year_range):
filtered_df = df.copy()
filtered_df = filtered_df[(filtered_df['firstAppearanceDate'] >= selected_year_range[0]) &
(filtered_df['firstAppearanceDate'] <= selected_year_range[1])]
if selected_country:
filtered_df = filtered_df[filtered_df['country'].isin(selected_country)]
if selected_gender:
filtered_df = filtered_df[filtered_df['gender'].isin(selected_gender)]
if selected_profession:
filtered_df = filtered_df[filtered_df['profession'].isin(selected_profession)]
country_currency = filtered_df.groupby(['country', 'currencyName', 'gender', 'profession', 'name', 'comments', 'billCount']).size().reset_index(name='count')
# Treemap
fig = px.treemap(
country_currency,
path=['country', 'currencyName', 'gender', 'profession', 'name'],
values='count',
color='count',
color_continuous_scale='Plasma',
hover_data={'count': True, 'gender': True, 'profession': True, 'comments': True, 'billCount': True},
#title=f'Who Ends Up on Money? Representation in {", ".join(selected_country)}' if selected_country else 'Who Ends Up on Money? Analyzing Banknote Figures'
)
fig.update_layout(
paper_bgcolor='#f8f9fa',
plot_bgcolor='#ffffff',
title_font=dict(size=24, color='#343a40'),
font=dict(color='#495057')
)
return fig
# Dash Layout
title_style = {'textAlign': 'center', 'fontSize': '40px', 'color': '#343a40'}
label_style = {'fontSize': '18px', 'fontWeight': 'bold', 'color': '#495057'}
dropdown_style = {'width': '100%'}
app.layout = dbc.Container(
[
dbc.Row(dbc.Col(html.H1('Who Ends Up appearing on Money? Analyzing Banknote Figures', style=title_style), width=12)),
html.Br(),
dbc.Row([
dbc.Col(html.Label('Select Year Range', style=label_style), width=12)
]),
dbc.Row([
dbc.Col(dcc.RangeSlider(
id='year-range-slider',
min=1869,
max=2021,
step=10,
marks={year: str(year) for year in range(1869, 2022, 20)},
value=[1869, 2021],
className='mb-4'
), width=12)
]),
dbc.Row([
dbc.Col(html.Label('Select Country', style=label_style), width=4),
dbc.Col(html.Label('Select Gender', style=label_style), width=4),
dbc.Col(html.Label('Select Profession', style=label_style), width=4),
], style={'margin-bottom': '10px'}),
dbc.Row([
dbc.Col(dcc.Dropdown(
id='country-dropdown',
options=[{'label': country, 'value': country} for country in df['country'].unique()],
value=[],
multi=True,
style=dropdown_style), width=4),
dbc.Col(dcc.Dropdown(
id='gender-dropdown',
options=[{'label': gender, 'value': gender} for gender in df['gender'].unique()],
value=[],
multi=True,
style=dropdown_style), width=4),
dbc.Col(dcc.Dropdown(
id='profession-dropdown',
options=[{'label': profession, 'value': profession} for profession in df['profession'].unique()],
value=[],
multi=True,
style=dropdown_style), width=4),
], style={'margin-bottom': '20px'}),
dbc.Row(dbc.Col(dcc.Graph(id='country-currency-representation', style={'height': '800px'}), width=12)),
],
fluid=True,
)
# Callback to update the graph
@app.callback(
Output('country-currency-representation', 'figure'),
[Input('year-range-slider', 'value'),
Input('country-dropdown', 'value'),
Input('gender-dropdown', 'value'),
Input('profession-dropdown', 'value')]
)
def update_graph(selected_year_range, selected_country, selected_gender, selected_profession):
return country_currency_representation(df, selected_country, selected_gender, selected_profession, selected_year_range)
# Run the app
if __name__ == '__main__':
app.run_server(debug=True)