from dash import Dash, dcc, html, Input, Output
import dash_ag_grid as dag
import plotly.express as px
import pandas as pd
import numpy as np
df = pd.read_csv('Argentina-bilateral-instruments-1810-2023.csv')
# Filter out rows where the "Counterpart ENG" field is missing
df = df[df['Counterpart ENG'].notna()].copy()
# Standardize column names by stripping whitespace and replacing spaces with underscores
df.columns = df.columns.str.strip().str.replace(' ', '_')
# Use the provided "Sign_year" column as the Year of the treaty signing.
# Create a new column "Year" for consistency in further analysis.
df['Year'] = df['Sign_year']
# Create a "Decade" column by grouping "Year" into decades.
df['Decade'] = df['Year'].apply(lambda x: (x // 10 * 10) if pd.notnull(x) else np.nan)
# Use the provided "Region_ENG" column for region information.
df["Region"] = df["Region_ENG"].str.strip()
# Use a mapping dictionary to further standardize region names.
region_mapping = {
# North America
"United States": "North America",
"USA": "North America",
"Canada": "North America",
"Mexico": "North America",
# South America
"Brazil": "South America",
"Chile": "South America",
"Peru": "South America",
"Colombia": "South America",
"Argentina": "South America",
"Uruguay": "South America",
"Paraguay": "South America",
"Bolivia": "South America",
"Ecuador": "South America",
"Venezuela": "South America",
# Europe
"Germany": "Europe",
"France": "Europe",
"United Kingdom": "Europe",
"Italy": "Europe",
"Spain": "Europe",
"Netherlands": "Europe",
"Belgium": "Europe",
"Sweden": "Europe",
"Norway": "Europe",
"Switzerland": "Europe",
"Poland": "Europe",
"Austria": "Europe",
"Czech Republic": "Europe",
"Slovakia": "Europe",
"Austro-Hungarian Monarchy": "Europe",
"Czechoslovakia": "Europe",
"Yugoslavia": "Europe",
"Serbia": "Europe",
"Prussia": "Europe",
# Eurasia / Near East
"Russia": "Eurasia",
"USSR": "Eurasia",
"Turkey": "Eurasia",
"Ottoman Empire": "Eurasia",
# Asia
"China": "Asia",
"Japan": "Asia",
"India": "Asia",
"South Korea": "Asia",
"Indonesia": "Asia",
"Malaysia": "Asia",
"Singapore": "Asia",
# Oceania
"Australia": "Oceania",
"New Zealand": "Oceania",
# Africa
"Egypt": "Africa",
"South Africa": "Africa",
"Nigeria": "Africa",
"Kenya": "Africa",
"Morocco": "Africa",
# Middle East
"Saudi Arabia": "Middle East",
"Israel": "Middle East",
"Iran": "Middle East",
"United Arab Emirates": "Middle East",
"Qatar": "Middle East"
}
df["Region"] = df["Region"].map(lambda x: region_mapping.get(x, x))
# Aggregate treaty counts per year
treaties_per_year = df.groupby('Year').size().reset_index(name='Count')
# Aggregate treaty counts per decade
treaties_per_decade = df.groupby('Decade').size().reset_index(name='Count')
# Top 20 counterparts by number of treaties
top20 = df['Counterpart_ENG'].value_counts().nlargest(20).reset_index(name='Count')
def apply_argentina_style(fig):
"""
Update the figure layout with Argentine color scheme.
Sky blue (#74acdf) and dark blue (#0033a0) are used alongside white.
"""
fig.update_layout(
plot_bgcolor="#ffffff", # white background for plot area
paper_bgcolor="#ffffff", # white background for the whole paper
font_color="#0033a0", # dark blue font color
title_font_color="#0033a0", # dark blue title font color
coloraxis=dict(colorbar=dict(bgcolor="#ffffff"))
)
return fig
# Create a bar chart for the top 20 counterparts
fig_bar = px.bar(
top20,
x='Counterpart_ENG',
y='Count',
title='Top 20 Counterparts by Number of Treaties',
labels={
'Counterpart_ENG': 'Counterpart',
'Count': 'Number of Treaties'
}
)
fig_bar = apply_argentina_style(fig_bar)
# Create a line chart for the treaty signings trend over the years
fig_line = px.line(
treaties_per_year,
x='Year',
y='Count',
title='Trend of Treaty Signings Over the Years',
labels={
'Year': 'Year',
'Count': 'Number of Treaties'
}
)
fig_line = apply_argentina_style(fig_line)
# Create a bar chart for treaties by decade
fig_decade = px.bar(
treaties_per_decade,
x='Decade',
y='Count',
title='Number of Treaties by Decade',
labels={
'Decade': 'Decade',
'Count': 'Number of Treaties'
}
)
fig_decade = apply_argentina_style(fig_decade)
# Enable suppress_callback_exceptions to allow callbacks for dynamically created components.
app = Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div([
html.H1(
'Argentina Treaty Library Analysis',
style={
'textAlign': 'center',
'color': '#0033a0'
}
),
# Year range slider filter
html.Div([
html.Label(
'Select Year Range:',
style={
'fontWeight': 'bold',
'color': '#0033a0'
}
),
dcc.RangeSlider(
id='year-slider',
min=int(df['Year'].min()),
max=int(df['Year'].max()),
value=[int(df["Year"].min()), int(df["Year"].max())],
marks={
str(year): str(year) for year in range(int(df["Year"].min()),
int(df["Year"].max()) + 1, 10)
}
)
], style={'margin': '20px'}),
# Region Dropdown (single-select with an "All Regions" option)
html.Div([
html.Label(
'Select Region:',
style={
'fontWeight': 'bold',
'color': '#0033a0'
}
),
dcc.Dropdown(
id='region-dropdown',
options=[{'label': 'All Regions', 'value': 'all'}] +
[{'label': r, 'value': r} for r in sorted(df['Region'].unique())],
value='all',
multi= False,
placeholder='Select region'
)
], style={'margin': '20px'}),
# Counterpart Dropdown (always in layout, initially hidden)
html.Div([
dcc.Dropdown(
id='counterpart-dropdown',
multi=True,
placeholder='Select counterpart(s)',
style={
'display': 'none'
}
)
], id='counterpart-container', style={'margin': '20px'}),
# Tabs for various analyses
dcc.Tabs(
id='tabs',
value='tab-table',
children=[
dcc.Tab(
label='Table',
value='tab-table'
),
dcc.Tab(
label='Visualizations',
value='tab-vis'
),
dcc.Tab(
label='Decade Analysis',
value='tab-decade'
),
dcc.Tab(
label='Regional Analysis',
value='tab-region'
),
dcc.Tab(
label='Deep Analytics',
value='tab-deep'
),
dcc.Tab(
label='Tags Analysis',
value='tab-tags'
)
]
),
html.Div(
id='tabs-content'
)
])
@app.callback(
[Output('counterpart-dropdown', 'options'),
Output('counterpart-dropdown', 'style')],
Input('region-dropdown', 'value')
)
def update_counterpart_dropdown(selected_region):
# If "All Regions" is selected or no region is selected, hide the counterpart dropdown.
if not selected_region or selected_region == 'all':
return [], {'display': 'none'}
else:
filtered = df[df['Region'] == selected_region]
options = [{'label': i, 'value': i} for i in sorted(filtered['Counterpart_ENG'].unique())]
return options, {'display': 'block'}
@app.callback(
Output('tabs-content', 'children'),
Input('tabs', 'value'),
Input('year-slider', 'value'),
Input('counterpart-dropdown', 'value'),
Input('region-dropdown', 'value')
)
def render_tab_content(tab, year_range, selected_counterparts, selected_region):
# Convert selected_region to string if it comes as a list
if isinstance(selected_region, list):
selected_region = selected_region[0] if selected_region else None
# Create a copy of the data for filtering.
filtered = df.copy()
if year_range:
filtered = filtered[(filtered['Year'] >= year_range[0]) & (filtered['Year'] <= year_range[1])]
if selected_region and selected_region != 'all':
filtered = filtered[filtered['Region'] == selected_region]
if selected_counterparts:
filtered = filtered[filtered['Counterpart_ENG'].isin(selected_counterparts)]
if tab == 'tab-table':
grid = dag.AgGrid(
id="data-grid",
rowData=filtered.to_dict('records'),
columnDefs=[{'field': col, 'filter': True, 'sortable': True} for col in filtered.columns],
dashGridOptions={
'pagination': True,
'paginationPageSize': 20
}
)
return grid
elif tab == 'tab-vis':
treaties_year = filtered.groupby('Year').size().reset_index(name='Count')
top20_filtered = filtered['Counterpart_ENG'].value_counts().nlargest(20).reset_index()
top20_filtered.columns = ['Counterpart_ENG', 'Count']
fig_line_filtered = px.line(
treaties_year,
x='Year',
y='Count',
title='Trend of Treaty Signings Over the Years (Filtered Data)',
labels={
'Year': 'Year',
'Count': 'Number of Treaties'
}
)
fig_line_filtered = apply_argentina_style(fig_line_filtered)
fig_bar_filtered = px.bar(
top20_filtered,
x='Counterpart_ENG',
y='Count',
title='Top 20 Counterparts (Filtered Data)',
labels={
'Counterpart_ENG': 'Counterpart',
'Count': 'Number of Treaties'
}
)
fig_bar_filtered = apply_argentina_style(fig_bar_filtered)
return html.Div([
dcc.Graph(figure=fig_line_filtered),
dcc.Graph(figure=fig_bar_filtered)
])
elif tab == 'tab-decade':
treaties_decade = filtered.groupby('Decade').size().reset_index(name='Count')
fig_decade_filtered = px.bar(
treaties_decade,
x='Decade',
y='Count',
title='Number of Treaties by Decade (Filtered Data)',
labels={
'Decade': 'Decade',
'Count': 'Number of Treaties'
}
)
fig_decade_filtered = apply_argentina_style(fig_decade_filtered)
return html.Div([dcc.Graph(figure=fig_decade_filtered)])
elif tab == 'tab-region':
treaties_by_region_year = filtered.groupby(['Year', 'Region']).size().reset_index(name='Count')
fig_region_year = px.area(
treaties_by_region_year,
x='Year',
y='Count',
color='Region',
title='Trend of Treaty Signings by Region Over Time',
labels={
'Year': 'Year',
'Count': 'Number of Treaties',
'Region': 'Region'
}
)
fig_region_year = apply_argentina_style(fig_region_year)
treaties_by_region = filtered.groupby('Region').size().reset_index(name='Count')
fig_region_bar = px.bar(
treaties_by_region,
x='Region',
y='Count',
title='Total Number of Treaties by Region',
labels={
'Region': 'Region',
'Count': 'Number of Treaties'
}
)
fig_region_bar = apply_argentina_style(fig_region_bar)
return html.Div([
dcc.Graph(figure=fig_region_year),
dcc.Graph(figure=fig_region_bar)
])
elif tab == 'tab-deep':
deep_df = filtered.copy()
deep_df['Decade'] = deep_df['Decade'].fillna('Unknown')
region_decade_counts = deep_df.groupby(['Region', 'Decade']).size().reset_index(name='Count')
fig_treemap = px.treemap(
region_decade_counts,
path=['Region', 'Decade'],
values='Count',
title='Treemap of Treaties by Region and Decade'
)
fig_treemap = apply_argentina_style(fig_treemap)
pivot_df = region_decade_counts.pivot(index='Region', columns='Decade', values='Count').fillna(0)
fig_heatmap = px.imshow(
pivot_df,
title='Heatmap of Treaty Counts by Region and Decade',
labels=
{'x': 'Decade',
'y': 'Region',
'color': 'Count'},
text_auto=True
)
fig_heatmap = apply_argentina_style(fig_heatmap)
return html.Div([
dcc.Graph(figure=fig_treemap),
dcc.Graph(figure=fig_heatmap)
])
elif tab == 'tab-tags':
tags_series = filtered['Tags'].dropna().str.split('\n')
all_tags = [tag.strip() for sublist in tags_series for tag in sublist if tag.strip() != '']
tag_counts = pd.Series(all_tags).value_counts().reset_index()
tag_counts.columns = ['Tag', 'Count']
fig_tags = px.bar(
tag_counts,
x='Tag',
y='Count',
title='Frequency of Tags in Treaty Data',
labels={'Tag': 'Tag', 'Count': 'Frequency'}
)
fig_tags = apply_argentina_style(fig_tags)
return html.Div([dcc.Graph(figure=fig_tags)])
if __name__ == '__main__':
app.run_server(debug=True)