In [1]:
# ============================================================
# CELL 1 — SETUP
# ============================================================
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import matplotlib.patches as mpatches
import seaborn as sns
from IPython.display import display, HTML
# ── Style ─────────────────────────────────────────────────────
plt.rcParams.update({
'figure.facecolor' : '#0d1117',
'axes.facecolor' : '#161b22',
'axes.edgecolor' : '#30363d',
'axes.labelcolor' : '#c9d1d9',
'axes.titlecolor' : '#ffffff',
'text.color' : '#c9d1d9',
'xtick.color' : '#8b949e',
'ytick.color' : '#8b949e',
'grid.color' : '#21262d',
'grid.linestyle' : '--',
'grid.alpha' : 0.6,
'font.family' : 'DejaVu Sans',
'axes.titlesize' : 14,
'axes.labelsize' : 11,
'legend.facecolor' : '#161b22',
'legend.edgecolor' : '#30363d',
'figure.dpi' : 120,
})
# ── Define Color ───────────────────────────────────────────────
GOLD = '#f0b429'
BLUE = '#58a6ff'
GREEN = '#3fb950'
RED = '#f85149'
PURPLE = '#bc8cff'
TEAL = '#39d353'
ORANGE = '#ffa657'
# ── Load ──────────────────────────────────────────────────────
# 1. Define a mapping dictionary to standardize column names
# Format: {'Old Name': 'New Standard Name'}
name_map = {
# Country / Region
'Country or region': 'Country',
# Rank and Score
'Happiness.Rank': 'Happiness Rank',
'Overall rank': 'Happiness Rank',
'Happiness.Score': 'Happiness Score',
'Score': 'Happiness Score',
# Economy / GDP
'Economy..GDP.per.Capita.': 'Economy (GDP per Capita)',
'GDP per capita': 'Economy (GDP per Capita)',
# Health / Life Expectancy
'Health..Life.Expectancy.': 'Health (Life Expectancy)',
'Healthy life expectancy': 'Health (Life Expectancy)',
# Trust / Corruption
'Trust..Government.Corruption.': 'Trust (Government Corruption)',
'Perceptions of corruption': 'Trust (Government Corruption)',
# Freedom
'Freedom to make life choices': 'Freedom',
# Family / Social Support
'Social support': 'Family',
# Dystopia
'Dystopia.Residual': 'Dystopia Residual'
}
dfs = []
# 2. Loop through and process
for year in range(2015, 2020):
path = f'/kaggle/input/datasets/organizations/unsdsn/world-happiness/{year}.csv'
temp_df = pd.read_csv(path)
# Standardize columns
temp_df = temp_df.rename(columns=name_map)
# Add year
temp_df['year'] = year
dfs.append(temp_df)
# 3. Create Master Dataframe
df = pd.concat(dfs, ignore_index=True)
# 4. Clean up: Drop columns that only appeared in one specific year (like Whisker or Confidence Intervals)
cols_to_keep = [
'Country', 'Region', 'Happiness Rank', 'Happiness Score',
'Economy (GDP per Capita)', 'Family', 'Health (Life Expectancy)',
'Freedom', 'Trust (Government Corruption)', 'Generosity',
'Dystopia Residual', 'year'
]
# Only keep columns that exist in the final dataframe
final_df = df[[c for c in cols_to_keep if c in df.columns]]
# Create a dictionary from the rows that have a Region (2015/2016 data)
region_lookup = (
final_df.dropna(subset=['Region'])
.set_index('Country')['Region']
.to_dict()
)
# Map those regions to the empty (NaN) cells
final_df['Region'] = final_df['Region'].fillna(final_df['Country'].map(region_lookup))
# Replace NaN with 0 in the Dystopia Residual column
final_df['Dystopia Residual'] = final_df['Dystopia Residual'].fillna(0)
# ── Convenience filters ───────────────────────────────────────
COUNTRIES = final_df[final_df['Country'].notna()].copy()
HISTORICAL = COUNTRIES[COUNTRIES['year'].isin(range(2015, 2019))].copy()
LATEST = COUNTRIES[COUNTRIES['year'] == 2019].copy()
COMBINED = COUNTRIES
print(f'✅ Dataset loaded: {final_df.shape[0]:,} rows × {final_df.shape[1]} columns')
print(f' Countries : {COUNTRIES["Country"].nunique()}')
print(f' Historical rows : {len(HISTORICAL):,} (2015–2018)')
print(f' Latest year snap : {len(LATEST):,} (2019)')
print(f' Combined year snap : {len(COMBINED):,} (2015-2019)')
✅ Dataset loaded: 782 rows × 12 columns Countries : 170 Historical rows : 626 (2015–2018) Latest year snap : 156 (2019) Combined year snap : 782 (2015-2019)
In [2]:
# ============================================================
# CELL 2 — DATA OVERVIEW
# ============================================================
print('=' * 60)
print(' DATA OVERVIEW')
print('=' * 60)
# ── Schema ────────────────────────────────────────────────────
print('\nColumn Schema:')
schema = pd.DataFrame({
'dtype' : final_df.dtypes.astype(str),
'non_null' : final_df.notna().sum(),
'null_pct' : (final_df.isnull().mean() * 100).round(1),
'sample_val' : [str(final_df[c].dropna().iloc[0])[:30] if final_df[c].notna().any() else 'N/A' for c in final_df.columns]
})
display(schema)
============================================================ DATA OVERVIEW ============================================================ Column Schema:
| dtype | non_null | null_pct | sample_val | |
|---|---|---|---|---|
| Country | object | 782 | 0.0 | Switzerland |
| Region | object | 774 | 1.0 | Western Europe |
| Happiness Rank | int64 | 782 | 0.0 | 1 |
| Happiness Score | float64 | 782 | 0.0 | 7.587 |
| Economy (GDP per Capita) | float64 | 782 | 0.0 | 1.39651 |
| Family | float64 | 782 | 0.0 | 1.34951 |
| Health (Life Expectancy) | float64 | 782 | 0.0 | 0.94143 |
| Freedom | float64 | 782 | 0.0 | 0.66557 |
| Trust (Government Corruption) | float64 | 781 | 0.1 | 0.41978 |
| Generosity | float64 | 782 | 0.0 | 0.29678 |
| Dystopia Residual | float64 | 782 | 0.0 | 2.51738 |
| year | int64 | 782 | 0.0 | 2015 |
In [3]:
# ============================================================
# CELL 3 — DATA PLOTS & HEATMAP
# ============================================================
plt.figure(figsize=(10, 6))
# Create the scatterplot
sns.scatterplot(data=LATEST, x='Economy (GDP per Capita)', y='Happiness Score', hue='Region', alpha=0.7)
plt.title('Correlation: GDP per Capita vs Happiness Score - 2019')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure(figsize=(12, 6))
# Create the boxplot
sns.boxplot(data=LATEST, x='Region', y='Happiness Score')
plt.xticks(rotation=45)
plt.title('Happiness Score Distribution by Region - 2019')
plt.show()
plt.figure(figsize=(10, 8))
# Add 'Dystopia Residual' to the drop list
corr = LATEST.select_dtypes('number').drop(columns=[
'year',
'Happiness Rank',
'Dystopia Residual'
]).corr()
# Create the heatmap
sns.heatmap(corr, annot=True, cmap='RdYlGn', fmt=".2f")
plt.title('Correlation Heatmap of Happiness Factors - 2019')
plt.show()
In [4]:
# ============================================================
# CELL 4 — DATA FILTER
# ============================================================
# 1. Filter data: Get Top 5 list and add 'United States'
top_countries = final_df[final_df['Happiness Rank'] <= 5]['Country'].unique().tolist()
# Add United States if it's not already in the top 5
if 'United States' not in top_countries:
top_countries.append('United States')
# Create the subset with the expanded list
subset = final_df[final_df['Country'].isin(top_countries)]
# 2. Create plot
plt.figure(figsize=(10, 6))
sns.lineplot(data=subset, x='year', y='Happiness Score', hue='Country', marker='o')
# --- FIX: Ensure X-axis only shows integer years ---
plt.xticks(subset['year'].unique().astype(int))
# 3. Fix the legend location
plt.legend(title='Country', bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
plt.title('Top 5 Happiest Countries vs. United States (Baseline)')
plt.tight_layout()
plt.show()
In [5]:
# Filter for latest year and get Top 10
top_10 = LATEST.nsmallest(10, 'Happiness Rank')
# Define the components to stack
components = ['Economy (GDP per Capita)', 'Family', 'Health (Life Expectancy)',
'Freedom', 'Trust (Government Corruption)', 'Generosity']
# Set style for dark theme
plt.style.use('dark_background')
fig, ax = plt.subplots(figsize=(12, 8))
# Plot
top_10.set_index('Country')[components].plot(kind='barh', stacked=True, ax=ax, colormap='viridis')
plt.title('What Makes the Top 10 Happy? (Factor Breakdown)', fontsize=15, pad=20)
plt.xlabel('Contribution to Happiness Score')
plt.ylabel('Country')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
# Invert y-axis to have #1 at the top
plt.gca().invert_yaxis()
plt.tight_layout()
plt.show()
In [6]:
# Aggregate data by Region
region_stats = LATEST.groupby('Region').agg({
'Happiness Score': 'mean',
'Economy (GDP per Capita)': 'mean',
'Country': 'count'
}).reset_index()
plt.figure(figsize=(10, 7))
plt.style.use('dark_background') # Ensures global text and axes are white
sns.set_style("dark", {"axes.facecolor": ".1"}) # Keeps grid subtle but dark
# Create bubble chart
scatter = sns.scatterplot(
data=region_stats,
x='Economy (GDP per Capita)',
y='Happiness Score',
size='Country',
hue='Region',
sizes=(200, 1000),
alpha=0.6
)
# Add global average lines
plt.axvline(region_stats['Economy (GDP per Capita)'].mean(), color='yellow', linestyle='--', alpha=0.5)
plt.axhline(region_stats['Happiness Score'].mean(), color='yellow', linestyle='--', alpha=0.5)
plt.title('Regional Quadrant: Economy Efficiency vs. Happiness', fontsize=14, color='white')
# --- FIX: White Legend Text ---
leg = plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', title="Region / Size = Country Count")
plt.setp(leg.get_texts(), color='white') # Set legend entries to white
plt.setp(leg.get_title(), color='white') # Set legend title to white
leg.get_frame().set_edgecolor('white') # Optional: add a subtle border
leg.get_frame().set_facecolor('#1e1e1e') # Match your dashboard card color
plt.show()
In [7]:
# Calculate Min, Max, and Mean per Region
range_df = LATEST.groupby('Region')['Happiness Score'].agg(['min', 'max', 'mean']).sort_values('mean')
# Ensure dark background for this specific plot
plt.style.use('dark_background')
plt.figure(figsize=(12, 8))
# Draw the "range line" (the whiskers)
plt.hlines(y=range_df.index, xmin=range_df['min'], xmax=range_df['max'], color='grey', alpha=0.5, linewidth=5)
# Plot the "Mean" as a bright yellow point
plt.scatter(range_df['mean'], range_df.index, color='yellow', s=100, label='Average Score', zorder=3)
# Plot the "Min" and "Max" as dots
plt.scatter(range_df['min'], range_df.index, color='#ff4b4b', s=50, label='Lowest Country', zorder=3)
plt.scatter(range_df['max'], range_df.index, color='#00ff9d', s=50, label='Highest Country', zorder=3)
plt.title('The Happiness Gap: Region Range & Average', fontsize=16, color='white')
plt.xlabel('Happiness Score', color='white')
plt.grid(axis='x', alpha=0.1)
# --- FIX: White Legend Text ---
leg = plt.legend(loc='lower right', frameon=True)
plt.setp(leg.get_texts(), color='white') # Set legend entries to white
leg.get_frame().set_facecolor('#1e1e1e') # Dark background for legend box
leg.get_frame().set_edgecolor('grey') # Subtle border
plt.tight_layout()
plt.show()
In [8]:
# 1. Prepare data for 2015 and 2019
df_2015 = COMBINED[COMBINED['year'] == 2015][['Country', 'Happiness Score']].rename(columns={'Happiness Score': 'Score_2015'})
df_2019 = COMBINED[COMBINED['year'] == 2019][['Country', 'Happiness Score']].rename(columns={'Happiness Score': 'Score_2019'})
# 2. Merge and calculate the delta
growth_df = pd.merge(df_2015, df_2019, on='Country')
growth_df['Improvement'] = growth_df['Score_2019'] - growth_df['Score_2015']
# 3. Identify top performer
best = growth_df.sort_values(by='Improvement', ascending=False).iloc[0]
# 4. Create and display the styled HTML block
summary_html = f"""
<div style="padding: 20px;
background-color: #1e1e1e;
border: 2px solid #FFD700;
border-radius: 10px;
text-align: center;
color: white;
font-family: Arial, sans-serif;
margin: 20px 0;">
<h2 style="color: #FFD700; margin-top: 0;">📈 Analysis Insight</h2>
<p style="font-size: 1.2em;">The <b>Most Improved Country</b> from 2015 to 2019 is:</p>
<h1 style="margin: 10px 0; color: #ffffff;">{best['Country']}</h1>
<p style="font-size: 1.1em;">Happiness Score Increase:
<span style="color: #00ff9d; font-weight: bold;">+{best['Improvement']:.3f}</span>
</p>
<hr style="border: 0; border-top: 1px solid #444; width: 50%;">
<p style="font-size: 0.9em; color: #aaa;">Comparison based on the World Happiness Report Dataset</p>
</div>
"""
display(HTML(summary_html))
📈 Analysis Insight
The Most Improved Country from 2015 to 2019 is:
Benin
Happiness Score Increase: +1.543
Comparison based on the World Happiness Report Dataset
In [9]:
# 1. Calculate the KPIs for the latest year
latest_year = COMBINED['year'].max()
kpi_data = COMBINED[COMBINED['year'] == latest_year]
avg_happiness = kpi_data['Happiness Score'].mean()
avg_gdp = kpi_data['Economy (GDP per Capita)'].mean()
total_countries = kpi_data['Country'].nunique()
# 2. Create the styled HTML block with 3 side-by-side cards
kpi_html = f"""
<div style="display: flex; justify-content: space-around; flex-wrap: wrap; gap: 20px; font-family: Arial, sans-serif; margin: 20px 0;">
<!-- KPI Card 1: Happiness -->
<div style="flex: 1; min-width: 200px; padding: 20px; background-color: #1e1e1e; border: 2px solid #FFD700; border-radius: 10px; text-align: center; color: white;">
<p style="color: #FFD700; font-size: 0.9em; text-transform: uppercase; margin-bottom: 10px;">Avg World Happiness</p>
<h1 style="margin: 0; font-size: 2.5em; color: #ffffff;">{avg_happiness:.2f}</h1>
<p style="font-size: 0.8em; color: #aaa; margin-top: 10px;">Global Index Score ({latest_year})</p>
</div>
<!-- KPI Card 2: Economy -->
<div style="flex: 1; min-width: 200px; padding: 20px; background-color: #1e1e1e; border: 2px solid #FFD700; border-radius: 10px; text-align: center; color: white;">
<p style="color: #FFD700; font-size: 0.9em; text-transform: uppercase; margin-bottom: 10px;">Avg GDP Per Capita</p>
<h1 style="margin: 0; font-size: 2.5em; color: #ffffff;">{avg_gdp:.2f}</h1>
<p style="font-size: 0.8em; color: #aaa; margin-top: 10px;">Economic Contribution</p>
</div>
<!-- KPI Card 3: Scope -->
<div style="flex: 1; min-width: 200px; padding: 20px; background-color: #1e1e1e; border: 2px solid #FFD700; border-radius: 10px; text-align: center; color: white;">
<p style="color: #FFD700; font-size: 0.9em; text-transform: uppercase; margin-bottom: 10px;">Dataset Scope</p>
<h1 style="margin: 0; font-size: 2.5em; color: #ffffff;">{total_countries}</h1>
<p style="font-size: 0.8em; color: #aaa; margin-top: 10px;">Participating Nations</p>
</div>
</div>
"""
display(HTML(kpi_html))
Avg World Happiness
5.41
Global Index Score (2019)
Avg GDP Per Capita
0.91
Economic Contribution
Dataset Scope
156
Participating Nations
In [10]:
# ============================================================
# CELL: INTERACTIVE HAPPINESS DASHBOARD
# ============================================================
from IPython.display import display, HTML
# 1. DATA CALCULATIONS (Using your LATEST and COMBINED dataframes)
latest_year = LATEST['year'].unique()[0]
avg_happiness = round(LATEST['Happiness Score'].mean(), 2)
avg_gdp = round(LATEST['Economy (GDP per Capita)'].mean(), 2)
avg_health = round(LATEST['Health (Life Expectancy)'].mean(), 2)
avg_trust = round(LATEST['Trust (Government Corruption)'].mean(), 2)
# High-level Counts
n_top_tier = int((LATEST['Happiness Score'] > 7.0).sum())
n_low_trust = int((LATEST['Trust (Government Corruption)'] < 0.05).sum())
n_high_freedom = int((LATEST['Freedom'] > 0.5).sum())
# Top Performers
happiest_country = LATEST.nlargest(1, 'Happiness Score')[['Country', 'Happiness Score']].values[0]
most_generous = LATEST.nlargest(1, 'Generosity')[['Country', 'Generosity']].values[0]
most_trusted = LATEST.nlargest(1, 'Trust (Government Corruption)')[['Country', 'Trust (Government Corruption)']].values[0]
# Historical Forecast/Trend (2015 vs Latest)
oldest_year = COMBINED['year'].min()
avg_old = COMBINED[COMBINED['year'] == oldest_year]['Happiness Score'].mean()
global_trend = round(avg_happiness - avg_old, 2)
# Top 10 Happiness Table
top10_hap = LATEST.nsmallest(10, 'Happiness Rank')[
['Country', 'Happiness Score', 'Economy (GDP per Capita)',
'Trust (Government Corruption)', 'Health (Life Expectancy)']
].dropna().reset_index(drop=True)
table_rows = ''
for i, row in top10_hap.iterrows():
table_rows += f"""
<tr>
<td>{int(i+1)}</td>
<td>{row['Country']}</td>
<td>{row['Happiness Score']:.2f}</td>
<td>{row['Economy (GDP per Capita)']:.2f}</td>
<td>{row['Trust (Government Corruption)']:.2f}</td>
<td><span class='score'>{row['Health (Life Expectancy)']:.2f}</span></td>
</tr>"""
# Bar Chart: Top 10 Economy scores
top10_econ = LATEST.nlargest(10, 'Economy (GDP per Capita)')[['Country', 'Economy (GDP per Capita)']].dropna()
bar_items = ''
max_e = top10_econ['Economy (GDP per Capita)'].max()
for _, row in top10_econ.iterrows():
pct = (row['Economy (GDP per Capita)'] / max_e) * 100
bar_items += f"""
<div class='bar-item'>
<span class='bar-label'>{row['Country'][:16]}</span>
<div class='bar-track'><div class='bar-fill' style='width:{pct:.0f}%'></div></div>
<span class='bar-val'>{row['Economy (GDP per Capita)']:.2f}</span>
</div>"""
# 2. THE HTML/CSS
html_dashboard = f"""
<style>
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@300;400;600;700&display=swap');
.dash {{ background:#0d1117; color:#c9d1d9; font-family:'IBM Plex Sans',sans-serif; padding:28px; border-radius:12px; max-width:1100px; margin:0 auto; border: 1px solid #FFD700; }}
.dash h1 {{ color:#fff; font-size:22px; font-weight:700; margin:0 0 4px; letter-spacing:-0.5px; }}
.dash .sub {{ color:#8b949e; font-size:13px; margin-bottom:24px; }}
.kpi-grid {{ display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:24px; }}
.kpi {{ background:#161b22; border:1px solid #21262d; border-radius:8px; padding:16px; text-align:center; }}
.kpi .val {{ font-size:26px; font-weight:700; font-family:'IBM Plex Mono'; color:#FFD700; line-height:1.1; }}
.kpi .lbl {{ font-size:11px; color:#8b949e; margin-top:4px; }}
.kpi.good .val {{ color:#3fb950; }}
.kpi.warn .val {{ color:#f0b429; }}
.kpi.danger .val {{ color:#f85149; }}
.grid2 {{ display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:24px; }}
.card {{ background:#161b22; border:1px solid #21262d; border-radius:8px; padding:18px; }}
.card h3 {{ color:#fff; font-size:13px; font-weight:600; margin:0 0 14px; text-transform:uppercase; letter-spacing:0.8px; }}
table {{ width:100%; border-collapse:collapse; font-size:12px; }}
th {{ padding:8px 10px; text-align:left; color:#8b949e; font-weight:600; font-size:11px; text-transform:uppercase; border-bottom:1px solid #30363d; }}
td {{ padding:7px 10px; border-bottom:1px solid #21262d; color:#c9d1d9; }}
.score {{ background:#FFD700; color:#000; padding:2px 8px; border-radius:20px; font-family:'IBM Plex Mono'; font-size:11px; font-weight:600; }}
.bar-item {{ display:flex; align-items:center; gap:8px; margin-bottom:7px; }}
.bar-label {{ font-size:11px; color:#8b949e; width:120px; text-align:right; }}
.bar-track {{ flex:1; background:#21262d; border-radius:4px; height:14px; }}
.bar-fill {{ height:100%; border-radius:4px; background:linear-gradient(90deg,#FFD700,#f0b429); }}
.bar-val {{ font-size:11px; font-family:'IBM Plex Mono'; color:#FFD700; width:40px; }}
.footer {{ text-align:center; font-size:11px; color:#484f58; margin-top:18px; }}
</style>
<div class='dash'>
<h1>📊 World Happiness Intelligence Dashboard — {latest_year}</h1>
<div class='sub'>Analyzing {len(LATEST)} Countries · Global Trends · Data via Kaggle</div>
<div class='kpi-grid'>
<div class='kpi'><div class='val'>{avg_happiness}</div><div class='lbl'>Global Happiness Avg</div></div>
<div class='kpi good'><div class='val'>{n_top_tier}</div><div class='lbl'>Countries Score > 7.0</div></div>
<div class='kpi warn'><div class='val'>{avg_trust:.2f}</div><div class='lbl'>Avg Gov't Trust Score</div></div>
<div class='kpi danger'><div class='val'>{n_low_trust}</div><div class='lbl'>Countries w/ Trust Deficit</div></div>
<div class='kpi'><div class='val'>{avg_gdp:.2f}</div><div class='lbl'>Median GDP Impact</div></div>
<div class='kpi good'><div class='val'>{global_trend:+}</div><div class='lbl'>Global Delta since 2015</div></div>
<div class='kpi'><div class='val'>{avg_health:.2f}</div><div class='lbl'>Life Expectancy Impact</div></div>
<div class='kpi good'><div class='val'>{happiest_country[1]:.1f}</div><div class='lbl'>Peak Score ({happiest_country[0]})</div></div>
</div>
<div class='grid2'>
<div class='card'>
<h3>Top 10 Economies (GDP Impact)</h3>
{bar_items}
</div>
<div class='card'>
<h3>Happiness Leaders — Top 10 Rank</h3>
<table>
<thead><tr><th>#</th><th>Country</th><th>Score</th><th>GDP</th><th>Trust</th><th>Health</th></tr></thead>
<tbody>{table_rows}</tbody>
</table>
</div>
</div>
<div class='card'>
<h3>Key Analyst Insights</h3>
<div style='display:grid; grid-template-columns: repeat(3, 1fr); gap: 10px; text-align:center;'>
<div><small style='color:#8b949e'>Highest Generosity</small><br><b style='color:#FFD700'>{most_generous[0]}</b></div>
<div><small style='color:#8b949e'>Highest Gov't Trust</small><br><b style='color:#FFD700'>{most_trusted[0]}</b></div>
<div><small style='color:#8b949e'>Highest Freedom</small><br><b style='color:#FFD700'>{LATEST.nlargest(1, 'Freedom')['Country'].values[0]}</b></div>
</div>
</div>
<div class='footer'>Steven Berggren Portfolio · World Happiness Report Analysis · Theme: Fire & Ice Matrix</div>
</div>
"""
display(HTML(html_dashboard))
📊 World Happiness Intelligence Dashboard — 2019
Analyzing 156 Countries · Global Trends · Data via Kaggle
5.41
Global Happiness Avg
16
Countries Score > 7.0
0.11
Avg Gov't Trust Score
40
Countries w/ Trust Deficit
0.91
Median GDP Impact
+0.03
Global Delta since 2015
0.73
Life Expectancy Impact
7.8
Peak Score (Finland)
Top 10 Economies (GDP Impact)
Happiness Leaders — Top 10 Rank
| # | Country | Score | GDP | Trust | Health |
|---|---|---|---|---|---|
| 1 | Finland | 7.77 | 1.34 | 0.39 | 0.99 |
| 2 | Denmark | 7.60 | 1.38 | 0.41 | 1.00 |
| 3 | Norway | 7.55 | 1.49 | 0.34 | 1.03 |
| 4 | Iceland | 7.49 | 1.38 | 0.12 | 1.03 |
| 5 | Netherlands | 7.49 | 1.40 | 0.30 | 1.00 |
| 6 | Switzerland | 7.48 | 1.45 | 0.34 | 1.05 |
| 7 | Sweden | 7.34 | 1.39 | 0.37 | 1.01 |
| 8 | New Zealand | 7.31 | 1.30 | 0.38 | 1.03 |
| 9 | Canada | 7.28 | 1.36 | 0.31 | 1.04 |
| 10 | Austria | 7.25 | 1.38 | 0.23 | 1.02 |
Key Analyst Insights
Highest Generosity
Myanmar
Myanmar
Highest Gov't Trust
Singapore
Singapore
Highest Freedom
Uzbekistan
Uzbekistan
In [11]:
# ============================================================
# CELL: EXECUTIVE HAPPINESS SUMMARY
# ============================================================
from IPython.display import display, HTML
# --- 1. Recompute all signals for Happiness context ---
# General Happiness
avg_happiness = round(LATEST['Happiness Score'].mean(), 2)
happiest_c = LATEST.nlargest(1, 'Happiness Score')[['Country', 'Happiness Score']].values[0]
sadest_c = LATEST.nsmallest(1, 'Happiness Score')[['Country', 'Happiness Score']].values[0]
med_happiness = round(LATEST['Happiness Score'].median(), 2)
n_top_tier = int((LATEST['Happiness Score'] > 7.0).sum())
# Economic & Health Drivers
med_gdp = round(LATEST['Economy (GDP per Capita)'].median(), 2)
med_health = round(LATEST['Health (Life Expectancy)'].median(), 2)
top_gdp_c = LATEST.nlargest(1, 'Economy (GDP per Capita)')[['Country', 'Economy (GDP per Capita)']].values[0]
# Social & Governance (Trust/Freedom)
med_trust = round(LATEST['Trust (Government Corruption)'].median(), 2)
n_low_trust = int((LATEST['Trust (Government Corruption)'] < 0.1).sum())
highest_trust_c = LATEST.nlargest(1, 'Trust (Government Corruption)')[['Country', 'Trust (Government Corruption)']].values[0]
med_freedom = round(LATEST['Freedom'].median(), 2)
# Historical Momentum (2015 to Latest)
oldest_year = COMBINED['year'].min()
latest_year = LATEST['year'].max()
growth_df = pd.merge(
COMBINED[COMBINED['year'] == oldest_year][['Country', 'Happiness Score']],
LATEST[['Country', 'Happiness Score']],
on='Country', suffixes=('_old', '_new')
)
growth_df['delta'] = growth_df['Happiness Score_new'] - growth_df['Happiness Score_old']
most_improved = growth_df.nlargest(1, 'delta')[['Country', 'delta']].values[0]
n_declining = int((growth_df['delta'] < 0).sum())
# --- 2. Render Executive Summary HTML ---
summary_html = f"""
<style>
@import url('https://googleapis.com');
.exec {{ background:#0d1117; color:#c9d1d9; font-family:'IBM Plex Sans',sans-serif; padding:32px; border-radius:12px; max-width:1000px; margin:0 auto; border:1px solid #FFD700; }}
.exec h1 {{ color:#fff; font-size:20px; font-weight:700; margin:0 0 4px; }}
.exec .meta {{ color:#8b949e; font-size:12px; margin-bottom:28px; font-family:'IBM Plex Mono'; }}
.section {{ margin-bottom:24px; }}
.section-title {{ color:#FFD700; font-size:13px; font-weight:700; text-transform:uppercase; letter-spacing:1px; border-bottom:1px solid #21262d; padding-bottom:6px; margin-bottom:12px; }}
.finding {{ background:#161b22; border-left:3px solid #FFD700; padding:10px 14px; margin-bottom:8px; border-radius:0 6px 6px 0; font-size:13px; line-height:1.6; }}
.finding.warn {{ border-left-color:#f0b429; }}
.finding.danger {{ border-left-color:#f85149; }}
.finding.good {{ border-left-color:#3fb950; }}
.num {{ font-family:'IBM Plex Mono'; color:#f0b429; font-weight:600; }}
.good-num {{ font-family:'IBM Plex Mono'; color:#3fb950; font-weight:600; }}
.red-num {{ font-family:'IBM Plex Mono'; color:#f85149; font-weight:600; }}
.highlight {{ color:#FFD700; font-weight:600; }}
</style>
<div class='exec'>
<h1>Executive Summary — World Happiness Analysis {latest_year}</h1>
<div class='meta'>{len(LATEST)} countries · 6 happiness drivers · {oldest_year}–{latest_year} Trend · Portfolio Analysis</div>
<div class='section'>
<div class='section-title'>Global Happiness Landscape</div>
<div class='finding good'>The global average happiness score reached <span class='good-num'>{avg_happiness}</span> in {latest_year}, led by <span class='highlight'>{happiest_c[0]}</span> as the world's happiest nation. <span class='num'>{n_top_tier}</span> countries now exceed a score of 7.0, marking a cluster of "high-wellbeing" states.</div>
<div class='finding warn'>A significant gap persists at the bottom of the index, with <span class='highlight'>{sadest_c[0]}</span> reporting the lowest global score at <span class='red-num'>{sadest_c[1]:.2f}</span>, driven by limited economic and health infrastructure.</div>
</div>
<div class='section'>
<div class='section-title'>Economic & Governance Drivers</div>
<div class='finding'>Economic contribution to happiness remains high with a median GDP impact score of <span class='num'>{med_gdp}</span>. However, the largest economy in the index, <span class='highlight'>{top_gdp_c[0]}</span>, does not always correlate linearly with the highest overall happiness score.</div>
<div class='finding danger'><span class='red-num'>{n_low_trust}</span> countries suffer from a "Trust Deficit," scoring below 0.1 on government transparency. <span class='highlight'>{highest_trust_c[0]}</span> remains the global benchmark for public trust with a score of <span class='good-num'>{highest_trust_c[1]:.2f}</span>.</div>
</div>
<div class='section'>
<div class='section-title'>Historical Momentum ({oldest_year} vs {latest_year})</div>
<div class='finding good'>The most improved nation in our longitudinal study is <span class='highlight'>{most_improved[0]}</span>, gaining <span class='good-num'>+{most_improved[1]:.3f}</span> in its total score since {oldest_year}.</div>
<div class='finding warn'>Despite global progress, <span class='num'>{n_declining}</span> nations have seen their happiness scores decrease over the last 5 years, suggesting that economic growth does not always prevent a decline in perceived wellbeing.</div>
</div>
<div class='footer-exec'>World Happiness Report Dataset · Steven Berggren Analyst Portfolio · Updated May 2026</div>
</div>
"""
display(HTML(summary_html))
Executive Summary — World Happiness Analysis 2019
Global Happiness Landscape
The global average happiness score reached 5.41 in 2019, led by Finland as the world's happiest nation. 16 countries now exceed a score of 7.0, marking a cluster of "high-wellbeing" states.
A significant gap persists at the bottom of the index, with South Sudan reporting the lowest global score at 2.85, driven by limited economic and health infrastructure.
Economic & Governance Drivers
Economic contribution to happiness remains high with a median GDP impact score of 0.96. However, the largest economy in the index, Qatar, does not always correlate linearly with the highest overall happiness score.
96 countries suffer from a "Trust Deficit," scoring below 0.1 on government transparency. Singapore remains the global benchmark for public trust with a score of 0.45.
Historical Momentum (2015 vs 2019)
The most improved nation in our longitudinal study is Benin, gaining +1.543 in its total score since 2015.
Despite global progress, 72 nations have seen their happiness scores decrease over the last 5 years, suggesting that economic growth does not always prevent a decline in perceived wellbeing.