# -*- coding: utf-8 -*-
"""
Created on Wed Jan 29 07:25:02 2025
@author: win11
"""
from dash import Dash, dcc, html, Input, Output
import dash_ag_grid as dag
import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
import dash_bootstrap_components as dbc
df = pd.read_csv("https://raw.githubusercontent.com/plotly/Figure-Friday/refs/heads/main/2025/week-4/Post45_NEAData_Final.csv")
df['age of writer'] = df.nea_grant_year - df.birth_year
df.sort_values(by='nea_grant_year', inplace=True)
df['teller'] = 1
df['sponsorships'] = df.groupby("nea_person_id")['teller'].cumsum()
dfs = df.groupby('nea_grant_year')['teller'].sum().reset_index()
color_discrete_map = {4: '#072F5F', 3: '#1261A0', 2: '#3895D3', 1: '#58CCED'}
fig = px.histogram(
df,
title='NEA sponsorships granted by year',
x="nea_grant_year",
color='sponsorships',
color_discrete_map=color_discrete_map,
labels={'nea_grant_year': 'Year', 'count': 'Total'},
nbins=60
)
fig.update_xaxes(range=[1966, 2025])
fig.update_layout(
legend=dict(x=.73, y=.98, title="Number of sponsorships")
)
fig.add_trace(go.Scatter(
x=dfs['nea_grant_year'],
y=dfs['teller'],
text=dfs['teller'],
mode='markers+text',
name="Total number of writers sponsored by NEA",
textposition='top center',
textfont=dict(size=12),
showlegend=True,
hoverinfo='skip'
))
for tr in fig.select_traces():
tr['name'] = tr['name'].replace('1', 'First sponsorship')
tr['name'] = tr['name'].replace('2', 'Second sponsorship')
tr['name'] = tr['name'].replace('3', 'Third sponsorship')
tr['name'] = tr['name'].replace('4', 'Fourth sponsorship')
app =Dash(external_stylesheets=[dbc.themes.SUPERHERO])
def filter_grid(filtered_data):
columnDefs = [
{"headerName": "Full Name", "field": "full_name_lastfirst"},
{"headerName": "Gender", "field": "gender"},
{"headerName": "Year", "field": "nea_grant_year"},
{"headerName": "Age of writer", "field": "age of writer"},
{"headerName": "Hometown", "field": "hometown"},
{"headerName": "Country", "field": "country"},
{"headerName": "Number of sponsorships", "field": "sponsorships"},
]
defaultColDef = {"resizable": False, "sortable": True, "editable": False}
return dag.AgGrid(
id="custom-component-graph-grid",
rowData=filtered_data.to_dict("records"),
columnDefs=columnDefs,
columnSize="autoSize",
defaultColDef=defaultColDef,
dashGridOptions={"pagination": True}
)
app.layout = dbc.Container([
dbc.Row(
dbc.Col( dcc.Graph(id="nea_histogram", figure=fig),)
),
dbc.Row([
dbc.Col(html.H2(id="title-container", style={'marginTop':'10px','marginBottom':'10px'}) )
]),
dbc.Row([
dbc.Col(html.Div(id="grid-container") , className='col-md-12')
])
])
@app.callback(
Output("grid-container", "children"),
Output("title-container", "children"),
Input("nea_histogram", "clickData")
)
def update_grid(clickData):
if clickData is None:
return filter_grid(df), 'All writers' # Show all data initially
# Extract year and sponsorship count from click event
clicked_year = clickData["points"][0]["x"]
clicked_neacount = clickData["points"][0]["curveNumber"] +1 # Adjust if needed
# Filter dataframe
filtered_df = df[
(df["nea_grant_year"] == clicked_year) &
(df["sponsorships"] == clicked_neacount)
]
#dict to insert the right number of sponsorships in the dynamic title
writer_text = {1:'first sponsorship', 2: 'second sponsorship', 3:'third sponsorship', 4: 'fourth sponsorship'}
#dynamic title construction
title = f"Writers who got their {writer_text[clicked_neacount]} in {clicked_year}"
return filter_grid(filtered_df), title
if __name__ == "__main__":
app.run(debug=True)