Code
import pandas as pd
import dash
from dash import dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import numpy as np
df = pd.read_csv(“live_expectancy_at_birth.csv”)
years = \[c for c in df.columns if c.isdigit()\]
REGIONS = \[
"East Asia & Pacific",
"Europe & Central Asia",
"Latin America & Caribbean",
"Middle East & North Africa",
"North America",
"South Asia",
"Sub-Saharan Africa",
\]
COUNTRY_TO_REGION = {
\# East Asia & Pacific
"Australia": "East Asia & Pacific",
"New Zealand": "East Asia & Pacific",
"Japan": "East Asia & Pacific",
"Korea, Rep.": "East Asia & Pacific",
"China": "East Asia & Pacific",
"Mongolia": "East Asia & Pacific",
"Indonesia": "East Asia & Pacific",
"Thailand": "East Asia & Pacific",
"Viet Nam": "East Asia & Pacific",
"Philippines": "East Asia & Pacific",
"Malaysia": "East Asia & Pacific",
"Singapore": "East Asia & Pacific",
"Myanmar": "East Asia & Pacific",
"Cambodia": "East Asia & Pacific",
"Lao PDR": "East Asia & Pacific",
"Brunei Darussalam": "East Asia & Pacific",
"Timor-Leste": "East Asia & Pacific",
"Papua New Guinea": "East Asia & Pacific",
"Fiji": "East Asia & Pacific",
"Solomon Islands": "East Asia & Pacific",
"Vanuatu": "East Asia & Pacific",
"Samoa": "East Asia & Pacific",
"Tonga": "East Asia & Pacific",
"Kiribati": "East Asia & Pacific",
"Micronesia, Fed. Sts.": "East Asia & Pacific",
"Palau": "East Asia & Pacific",
"Marshall Islands": "East Asia & Pacific",
"Nauru": "East Asia & Pacific",
"Tuvalu": "East Asia & Pacific",
"Hong Kong SAR, China": "East Asia & Pacific",
"Macao SAR, China": "East Asia & Pacific",
"Korea, Dem. People's Rep.": "East Asia & Pacific",
\# Europe & Central Asia
"United Kingdom": "Europe & Central Asia",
"Germany": "Europe & Central Asia",
"France": "Europe & Central Asia",
"Italy": "Europe & Central Asia",
"Spain": "Europe & Central Asia",
"Poland": "Europe & Central Asia",
"Romania": "Europe & Central Asia",
"Netherlands": "Europe & Central Asia",
"Belgium": "Europe & Central Asia",
"Czechia": "Europe & Central Asia",
"Greece": "Europe & Central Asia",
"Portugal": "Europe & Central Asia",
"Sweden": "Europe & Central Asia",
"Hungary": "Europe & Central Asia",
"Austria": "Europe & Central Asia",
"Switzerland": "Europe & Central Asia",
"Bulgaria": "Europe & Central Asia",
"Denmark": "Europe & Central Asia",
"Finland": "Europe & Central Asia",
"Norway": "Europe & Central Asia",
"Ireland": "Europe & Central Asia",
"Croatia": "Europe & Central Asia",
"Slovak Republic": "Europe & Central Asia",
"Lithuania": "Europe & Central Asia",
"Slovenia": "Europe & Central Asia",
"Latvia": "Europe & Central Asia",
"Estonia": "Europe & Central Asia",
"Cyprus": "Europe & Central Asia",
"Luxembourg": "Europe & Central Asia",
"Malta": "Europe & Central Asia",
"Iceland": "Europe & Central Asia",
"Albania": "Europe & Central Asia",
"North Macedonia": "Europe & Central Asia",
"Serbia": "Europe & Central Asia",
"Bosnia and Herzegovina": "Europe & Central Asia",
"Montenegro": "Europe & Central Asia",
"Kosovo": "Europe & Central Asia",
"Moldova": "Europe & Central Asia",
"Ukraine": "Europe & Central Asia",
"Belarus": "Europe & Central Asia",
"Russian Federation": "Europe & Central Asia",
"Turkiye": "Europe & Central Asia",
"Kazakhstan": "Europe & Central Asia",
"Uzbekistan": "Europe & Central Asia",
"Turkmenistan": "Europe & Central Asia",
"Tajikistan": "Europe & Central Asia",
"Kyrgyz Republic": "Europe & Central Asia",
"Azerbaijan": "Europe & Central Asia",
"Georgia": "Europe & Central Asia",
"Armenia": "Europe & Central Asia",
"Andorra": "Europe & Central Asia",
"Monaco": "Europe & Central Asia",
"San Marino": "Europe & Central Asia",
"Liechtenstein": "Europe & Central Asia",
\# Latin America & Caribbean
"Brazil": "Latin America & Caribbean",
"Mexico": "Latin America & Caribbean",
"Argentina": "Latin America & Caribbean",
"Colombia": "Latin America & Caribbean",
"Peru": "Latin America & Caribbean",
"Venezuela, RB": "Latin America & Caribbean",
"Chile": "Latin America & Caribbean",
"Ecuador": "Latin America & Caribbean",
"Guatemala": "Latin America & Caribbean",
"Cuba": "Latin America & Caribbean",
"Bolivia": "Latin America & Caribbean",
"Dominican Republic": "Latin America & Caribbean",
"Honduras": "Latin America & Caribbean",
"Paraguay": "Latin America & Caribbean",
"Nicaragua": "Latin America & Caribbean",
"El Salvador": "Latin America & Caribbean",
"Costa Rica": "Latin America & Caribbean",
"Panama": "Latin America & Caribbean",
"Uruguay": "Latin America & Caribbean",
"Jamaica": "Latin America & Caribbean",
"Trinidad and Tobago": "Latin America & Caribbean",
"Guyana": "Latin America & Caribbean",
"Suriname": "Latin America & Caribbean",
"Belize": "Latin America & Caribbean",
"Bahamas, The": "Latin America & Caribbean",
"Barbados": "Latin America & Caribbean",
"Haiti": "Latin America & Caribbean",
"St. Lucia": "Latin America & Caribbean",
"Grenada": "Latin America & Caribbean",
"St. Vincent and the Grenadines": "Latin America & Caribbean",
"Antigua and Barbuda": "Latin America & Caribbean",
"Dominica": "Latin America & Caribbean",
"St. Kitts and Nevis": "Latin America & Caribbean",
\# Middle East & North Africa
"Egypt, Arab Rep.": "Middle East & North Africa",
"Iran, Islamic Rep.": "Middle East & North Africa",
"Iraq": "Middle East & North Africa",
"Saudi Arabia": "Middle East & North Africa",
"Yemen, Rep.": "Middle East & North Africa",
"Syrian Arab Republic": "Middle East & North Africa",
"Jordan": "Middle East & North Africa",
"United Arab Emirates": "Middle East & North Africa",
"Israel": "Middle East & North Africa",
"Lebanon": "Middle East & North Africa",
"Libya": "Middle East & North Africa",
"Tunisia": "Middle East & North Africa",
"Morocco": "Middle East & North Africa",
"Algeria": "Middle East & North Africa",
"Oman": "Middle East & North Africa",
"Kuwait": "Middle East & North Africa",
"Qatar": "Middle East & North Africa",
"Bahrain": "Middle East & North Africa",
"West Bank and Gaza": "Middle East & North Africa",
"Djibouti": "Middle East & North Africa",
\# North America
"United States": "North America",
"Canada": "North America",
\# South Asia
"India": "South Asia",
"Pakistan": "South Asia",
"Bangladesh": "South Asia",
"Afghanistan": "South Asia",
"Nepal": "South Asia",
"Sri Lanka": "South Asia",
"Bhutan": "South Asia",
"Maldives": "South Asia",
\# Sub-Saharan Africa
"Nigeria": "Sub-Saharan Africa",
"Ethiopia": "Sub-Saharan Africa",
"Congo, Dem. Rep.": "Sub-Saharan Africa",
"South Africa": "Sub-Saharan Africa",
"Tanzania": "Sub-Saharan Africa",
"Kenya": "Sub-Saharan Africa",
"Uganda": "Sub-Saharan Africa",
"Sudan": "Sub-Saharan Africa",
"Ghana": "Sub-Saharan Africa",
"Mozambique": "Sub-Saharan Africa",
"Madagascar": "Sub-Saharan Africa",
"Cote d'Ivoire": "Sub-Saharan Africa",
"Cameroon": "Sub-Saharan Africa",
"Niger": "Sub-Saharan Africa",
"Burkina Faso": "Sub-Saharan Africa",
"Mali": "Sub-Saharan Africa",
"Malawi": "Sub-Saharan Africa",
"Zambia": "Sub-Saharan Africa",
"Senegal": "Sub-Saharan Africa",
"Chad": "Sub-Saharan Africa",
"Somalia, Fed. Rep.": "Sub-Saharan Africa",
"Zimbabwe": "Sub-Saharan Africa",
"Guinea": "Sub-Saharan Africa",
"Rwanda": "Sub-Saharan Africa",
"Benin": "Sub-Saharan Africa",
"Burundi": "Sub-Saharan Africa",
"South Sudan": "Sub-Saharan Africa",
"Togo": "Sub-Saharan Africa",
"Sierra Leone": "Sub-Saharan Africa",
"Congo, Rep.": "Sub-Saharan Africa",
"Liberia": "Sub-Saharan Africa",
"Central African Republic": "Sub-Saharan Africa",
"Mauritania": "Sub-Saharan Africa",
"Eritrea": "Sub-Saharan Africa",
"Namibia": "Sub-Saharan Africa",
"Gambia, The": "Sub-Saharan Africa",
"Botswana": "Sub-Saharan Africa",
"Gabon": "Sub-Saharan Africa",
"Lesotho": "Sub-Saharan Africa",
"Guinea-Bissau": "Sub-Saharan Africa",
"Equatorial Guinea": "Sub-Saharan Africa",
"Mauritius": "Sub-Saharan Africa",
"Eswatini": "Sub-Saharan Africa",
"Comoros": "Sub-Saharan Africa",
"Cabo Verde": "Sub-Saharan Africa",
"Sao Tome and Principe": "Sub-Saharan Africa",
"Seychelles": "Sub-Saharan Africa",
}
df_regions = df\[df\[“Country Name”\].isin(REGIONS)\].copy()
aggregated_names = \[
"World",
"High income",
"Low income",
"Lower middle income",
"Upper middle income",
"Middle income",
"OECD members",
"European Union",
"Euro area",
"Arab World",
"IDA",
"IBRD",
"Small states",
"Fragile",
"Heavily indebted",
"Least developed",
"Late-demographic",
"Early-demographic",
"Post-demographic",
"Pre-demographic",
\]
df_countries = df\[
\~df\["Country Name"\].str.contains("|".join(aggregated_names), case=False, na=False)
\]
df_countries = df_countries\[\~df_countries\[“Country Name”\].isin(REGIONS)\]
df_countries = df_countries\[
df_countries[“Country Name”].isin(COUNTRY_TO_REGION.keys())
\].copy()
df_countries\[“Region”\] = df_countries\[“Country Name”\].map(COUNTRY_TO_REGION)
year_marks = {i: years\[i\] for i in range(0, len(years), 10)}
year_marks\[len(years) - 1\] = years\[-1\]
app = dash.Dash(\_*name*\_, external_stylesheets=\[dbc.themes.DARKLY\])
def create_kpi_card(title, value, icon, color):
return dbc.Card(
\[
dbc.CardBody(
\[
html.Div(
\[
html.I(
className=f"fas {icon} fa-2x", style={"color": color}
),
html.Div(
\[
html.P(
title,
className="text-muted mb-0",
style={"fontSize": "0.85rem"},
),
html.H4(
value,
className="mb-0 fw-bold",
style={"color": color},
),
\],
style={"marginLeft": "15px"},
),
\],
style={"display": "flex", "alignItems": "center"},
)
\]
)
\],
className="shadow-sm",
style={"backgroundColor": "#2d2d2d", "border": "none"},
)
dark_select_style = {
"backgroundColor": "#2d2d2d",
"color": "#ffffff",
"border": "1px solid #555",
"borderRadius": "6px",
"padding": "6px 10px",
"height": "38px",
"cursor": "pointer",
"appearance": "none",
"WebkitAppearance": "none",
"MozAppearance": "none",
"outline": "none",
}
app.layout = dbc.Container(
\[
\# Header
dbc.Row(
\[
dbc.Col(
\[
html.H2(
"Life Expectancy Dashboard",
className="mb-0 fw-bold",
style={"color": "#fff", "paddingTop": "20px"},
),
html.P(
"Global Life Expectancy Analysis", className="text-muted"
),
\],
width=6,
),
dbc.Col(
\[
html.Div(
\[
dbc.Label("Year", className="text-light me-2"),
dbc.Select(
id="year-dropdown",
options=\[
{"label": y, "value": y} for y in years
\],
value=years\[-1\],
style=dark_select_style,
),
\],
style={
"display": "flex",
"alignItems": "right",
"justifyContent": "flex-end",
"paddingTop": "25px",
"gap": "10px",
},
)
\],
width=2, style={"textAlign": "right"}
),
\]
),
\# KPI Cards
dbc.Row(
\[
dbc.Col(id="kpi-1", width=2),
dbc.Col(id="kpi-2", width=2),
dbc.Col(id="kpi-3", width=2),
dbc.Col(id="kpi-4", width=2),
dbc.Col(id="kpi-5", width=2),
dbc.Col(id="kpi-6", width=2),
\],
className="mb-4",
),
\# Filters Row
dbc.Row(
\[
dbc.Col(
\[
dbc.Label("Region", className="text-light"),
dbc.Select(
id="region",
options=\[{"label": "All Regions", "value": "all"}\]
+ \[{"label": r, "value": r} for r in REGIONS\],
value="all",
style=dark_select_style,
),
\],
width=3,
),
dbc.Col(
\[
dbc.Label("Map Metric", className="text-light"),
dbc.Select(
id="metric",
options=\[
{
"label": "Absolute Value (years)",
"value": "absolute",
},
{
"label": "Change Since Start (%)",
"value": "change_start",
},
{
"label": "10-Year Change (%)",
"value": "change_10y",
},
{"label": "Vs. Global Average (%)", "value": "vs_avg"},
\],
value="absolute",
style=dark_select_style,
),
\],
width=3,
),
\],
className="mb-4",
),
\# Charts Row with table
dbc.Row(
\[
\# Map
dbc.Col(
\[
dbc.Card(
\[
dbc.CardHeader(
"World Map",
style={
"backgroundColor": "#3d3d3d",
"color": "#fff",
"fontWeight": "bold",
},
),
dbc.CardBody(
\[dcc.Graph(id="map-chart", style={"height": "500px"})\],
style={"padding": "10px"},
),
\],
style={"backgroundColor": "#2d2d2d", "border": "none"},
className="shadow",
)
\],
width=8,
),
\# Country table
dbc.Col(
\[
dbc.Card(
\[
dbc.CardHeader(
id="table-title",
children="Countries",
style={
"backgroundColor": "#3d3d3d",
"color": "#fff",
"fontWeight": "bold",
"padding": "10px 15px",
},
),
dbc.CardBody(
id="table-body",
style={"padding": "0px", "maxHeight": "500px", "overflowY": "auto"},
),
\],
style={"backgroundColor": "#2d2d2d", "border": "none"},
className="shadow",
)
\],
width=4,
),
\],
className="mb-4",
),
html.Link(
rel="stylesheet",
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css",
),
\],
fluid=True,
style={"backgroundColor": "#1e1e1e", "minHeight": "100vh", "padding": "20px"},
)
@app.callback(
\[
Output("kpi-1", "children"),
@app.callbackutput("kpi-2", "children"),
Output("kpi-3", "children"),
Output("kpi-4", "children"),
Output("kpi-5", "children"),
Output("kpi-6", "children"),
\],
\[Input("year-dropdown", "value"), Input("region", "value")\],
)
def update_kpis(year, region):
first_year = years\[0\]
if region == "all":
dff = df_countries\[\["Country Name", year, first_year\]\].dropna()
else:
dff = df_countries\[df_countries\["Region"\] == region\]\[
\["Country Name", year, first_year\]
\].dropna()
avg_life = dff\[year\].mean()
max_life = dff\[year\].max()
min_life = dff\[year\].min()
median_life = dff\[year\].median()
country_count = len(dff)
avg_first = dff\[first_year\].mean()
global_change = ((avg_life - avg_first) / avg_first) \* 100 if avg_first > 0 else 0
change_text = (
f"+{global_change:.1f}%" if global_change > 0 else f"{global_change:.1f}%"
)
return (
create_kpi_card("Average", f"{avg_life:.1f} yrs", "fa-heart-pulse", "#e74c3c"),
create_kpi_card("Highest", f"{max_life:.1f} yrs", "fa-arrow-up", "#2ecc71"),
create_kpi_card("Lowest", f"{min_life:.1f} yrs", "fa-arrow-down", "#f39c12"),
create_kpi_card("Median", f"{median_life:.1f} yrs", "fa-chart-line", "#9b59b6"),
create_kpi_card("Countries", f"{country_count}", "fa-globe", "#ffffff"),
create_kpi_card(
f"Change ({first_year})", change_text, "fa-percent", "#ffffff"
@app.callback ),
)
@app.callback(
Output("map-chart", "figure"),
\[Input("y@app.callbackar-dropdown", "value"), Input("region", "value"), Input("metric", "value")\],
)
def update_map(year, region, metric):
year_idx = years.index(year)
first_year = years\[0\]
year_10_prior_idx = max(0, year_idx - 10)
year_10_prior = years\[year_10_prior_idx\]
if region == "all":
dff = df_countries\[\["Country Name", "Country Code", "Region"\] + years\].dropna(
subset=\[year\]
)
else:
dff = df_countries\[df_countries\["Region"\] == region\]\[
\["Country Name", "Country Code", "Region"\] + years
\].dropna(subset=\[year\])
global_avg = dff\[year\].mean()
if metric == "absolute":
dff\["value"\] = dff\[year\]
color_title = "Years"
color_suffix = " yrs"
color_scale = "RdYlGn"
elif metric == "change_start":
dff = dff.dropna(subset=\[first_year\])
dff\["value"\] = (dff\[year\] - dff\[first_year\]) / dff\[first_year\] \* 100
color_title = f"Change since {first_year}"
color_suffix = "%"
color_scale = "RdYlGn"
elif metric == "change_10y":
dff = dff.dropna(subset=\[year_10_prior\])
dff\["value"\] = (dff\[year\] - dff\[year_10_prior\]) / dff\[year_10_prior\] \* 100
color_title = "10-Year Change"
color_suffix = "%"
color_scale = "RdYlGn"
else:
dff\["value"\] = (dff\[year\] - global_avg) / global_avg \* 100
color_title = "Vs. Average"
color_suffix = "%"
color_scale = "RdBu"
fig = px.choropleth(
dff,
locations="Country Code",
color="value",
hover_name="Country Name",
hover_data={"Country Code": False, "Region": True, "value": ":.1f"},
color_continuous_scale=color_scale,
range_color=\[dff\["value"\].min(), dff\["value"\].max()\],
custom_data=\["Country Name"\],
)
scope_map = {
"East Asia & Pacific": "asia",
"Europe & Central Asia": "europe",
"Latin America & Caribbean": "south america",
"Middle East & North Africa": "africa",
"North America": "north america",
"South Asia": "asia",
"Sub-Saharan Africa": "africa",
}
if region != "all" and region in scope_map:
fig.update_geos(scope=scope_map\[region\])
else:
fig.update_geos(
showframe=False,
showcoastlines=True,
projection_type="natural earth",
bgcolor="#1e1e1e",
landcolor="#3d3d3d",
oceancolor="#1e1e1e",
)
fig.update_layout(
paper_bgcolor="#2d2d2d",
plot_bgcolor="#2d2d2d",
geo=dict(bgcolor="#2d2d2d"),
margin=dict(l=0, r=0, t=0, b=0),
coloraxis_colorbar=dict(
title=dict(text=color_title, font=dict(color="#fff")),
ticksuffix=color_suffix,
bgcolor="#2d2d2d",
tickfont=dict(color="#fff"),
@app.callback ),
)
return fig
@app.callback(
\[
Output("table-title", "children"),@app.callback
Output("table-body", "children"),
\],
\[Input("year-dropdown", "value"), Input("region", "value")\],
)
def update_country_table(year, region):
if region == “all”:
dff = df_countries\[\["Country Name", "Country Code", year\]\].dropna(subset=\[year\])
else:
dff = df_countries\[df_countries\["Region"\] == region\]\[
\["Country Name", "Country Code", year\]
\].dropna(subset=\[year\])
min_val = dff[year].min()
max_val = dff[year].max()
dff = dff.sort_values(year, ascending=False).reset_index(drop=True)
table_rows = []
for idx, row in dff.iterrows():
country_code = row\["Country Code"\]
flag_code = country_code\[:2\].lower() if len(country_code) >= 2 else ""
flag_url = f"https://flagcdn.com/w40/{flag_code}.png"
life_exp = row\[year\]
\# Color gradient from red (low) to green (high)
if max_val > min_val:
ratio = (life_exp - min_val) / (max_val - min_val)
else:
ratio = 0.5
\# Interpolate between red (#e74c3c) and green (#2ecc71)
r = int(231 + (46 - 231) \* ratio)
g = int(76 + (204 - 76) \* ratio)
b = int(60 + (113 - 60) \* ratio)
value_color = f"rgb({r}, {g}, {b})"
table_rows.append(
html.Tr(
\[
html.Td(
f"{idx + 1}",
style={"padding": "8px 10px", "color": "#888", "width": "35px", "textAlign": "center"}
),
html.Td(
html.Img(src=flag_url, style={"width": "24px", "borderRadius": "2px"}),
style={"padding": "8px 5px", "width": "35px"}
),
html.Td(
row\["Country Name"\],
style={"padding": "8px 10px", "color": "#fff", "fontWeight": "500"}
),
html.Td(
f"{life_exp:.1f}",
style={"padding": "8px 10px", "color": value_color, "fontWeight": "bold", "textAlign": "right"}
),
\],
style={"borderBottom": "1px solid #3d3d3d"}
)
)
table = html.Table(
\[
html.Thead(
html.Tr(
\[
html.Th("#", style={"padding": "10px", "color": "#888", "fontWeight": "normal", "textAlign": "center", "width": "35px"}),
html.Th("", style={"padding": "10px", "width": "35px"}),
html.Th("Country", style={"padding": "10px", "color": "#888", "fontWeight": "normal"}),
html.Th("Years", style={"padding": "10px", "color": "#888", "fontWeight": "normal", "textAlign": "right"}),
\],
style={"borderBottom": "2px solid #555", "position": "sticky", "top": "0", "backgroundColor": "#2d2d2d"}
)
),
html.Tbody(table_rows)
\],
style={"width": "100%", "borderCollapse": "collapse"}
)
title = f"Countries ({len(dff)})" if region == “all” else f"{region} ({len(dff)})"
return title, table
if _name_ == “_main_”:
app.run(debug=True)```