This notebook is a brief exploration of the World Happiness Index to observe how it has changed over time, what global disparities there are, and what variables contribute a country's happiness. Special consideration will be given to Colombia.
This analysis will make use of the 2021 World Index Report database as well as one that contains historical data.
Website of the World Happiness Report: https://worldhappiness.report/
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings("ignore")
import matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.colors import ListedColormap
from matplotlib import cm
import seaborn as sns
import plotly.express as px
from pywaffle import Waffle
# get data
df21 = pd.read_csv('data/world-happiness-report-2021.csv')
dfh = pd.read_csv('data/world-happiness-report.csv')
df08_21=pd.read_excel('data/WHI 2008-2021.xls')
# renaming columns for easier merge later
df21.rename(columns={'Country name': 'Country'}, inplace=True)
dfh.rename(columns={'Country name': 'Country', 'Life Ladder': 'Ladder score'}, inplace=True)
df08_21.rename(columns={'Country name': 'Country', 'Life Ladder': 'Ladder score'}, inplace=True)
# safety copies
safety_df21 = df21.copy()
safety_dfh = dfh.copy()
safefety_08_21 = df08_21.copy()
# font
plt.rcParams["font.family"] = 'sans serif'
df21.head()
Country | Regional indicator | Ladder score | Standard error of ladder score | upperwhisker | lowerwhisker | Logged GDP per capita | Social support | Healthy life expectancy | Freedom to make life choices | Generosity | Perceptions of corruption | Ladder score in Dystopia | Explained by: Log GDP per capita | Explained by: Social support | Explained by: Healthy life expectancy | Explained by: Freedom to make life choices | Explained by: Generosity | Explained by: Perceptions of corruption | Dystopia + residual | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Finland | Western Europe | 7.842 | 0.032 | 7.904 | 7.780 | 10.775 | 0.954 | 72.0 | 0.949 | -0.098 | 0.186 | 2.43 | 1.446 | 1.106 | 0.741 | 0.691 | 0.124 | 0.481 | 3.253 |
1 | Denmark | Western Europe | 7.620 | 0.035 | 7.687 | 7.552 | 10.933 | 0.954 | 72.7 | 0.946 | 0.030 | 0.179 | 2.43 | 1.502 | 1.108 | 0.763 | 0.686 | 0.208 | 0.485 | 2.868 |
2 | Switzerland | Western Europe | 7.571 | 0.036 | 7.643 | 7.500 | 11.117 | 0.942 | 74.4 | 0.919 | 0.025 | 0.292 | 2.43 | 1.566 | 1.079 | 0.816 | 0.653 | 0.204 | 0.413 | 2.839 |
3 | Iceland | Western Europe | 7.554 | 0.059 | 7.670 | 7.438 | 10.878 | 0.983 | 73.0 | 0.955 | 0.160 | 0.673 | 2.43 | 1.482 | 1.172 | 0.772 | 0.698 | 0.293 | 0.170 | 2.967 |
4 | Netherlands | Western Europe | 7.464 | 0.027 | 7.518 | 7.410 | 10.932 | 0.942 | 72.4 | 0.913 | 0.175 | 0.338 | 2.43 | 1.501 | 1.079 | 0.753 | 0.647 | 0.302 | 0.384 | 2.798 |
df21.shape
(149, 20)
df21.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 149 entries, 0 to 148 Data columns (total 20 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Country 149 non-null object 1 Regional indicator 149 non-null object 2 Ladder score 149 non-null float64 3 Standard error of ladder score 149 non-null float64 4 upperwhisker 149 non-null float64 5 lowerwhisker 149 non-null float64 6 Logged GDP per capita 149 non-null float64 7 Social support 149 non-null float64 8 Healthy life expectancy 149 non-null float64 9 Freedom to make life choices 149 non-null float64 10 Generosity 149 non-null float64 11 Perceptions of corruption 149 non-null float64 12 Ladder score in Dystopia 149 non-null float64 13 Explained by: Log GDP per capita 149 non-null float64 14 Explained by: Social support 149 non-null float64 15 Explained by: Healthy life expectancy 149 non-null float64 16 Explained by: Freedom to make life choices 149 non-null float64 17 Explained by: Generosity 149 non-null float64 18 Explained by: Perceptions of corruption 149 non-null float64 19 Dystopia + residual 149 non-null float64 dtypes: float64(18), object(2) memory usage: 23.4+ KB
df21.describe()
Ladder score | Standard error of ladder score | upperwhisker | lowerwhisker | Logged GDP per capita | Social support | Healthy life expectancy | Freedom to make life choices | Generosity | Perceptions of corruption | Ladder score in Dystopia | Explained by: Log GDP per capita | Explained by: Social support | Explained by: Healthy life expectancy | Explained by: Freedom to make life choices | Explained by: Generosity | Explained by: Perceptions of corruption | Dystopia + residual | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 1.490000e+02 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 | 149.000000 |
mean | 5.532839 | 0.058752 | 5.648007 | 5.417631 | 9.432208 | 0.814745 | 64.992799 | 0.791597 | -0.015134 | 0.727450 | 2.430000e+00 | 0.977161 | 0.793315 | 0.520161 | 0.498711 | 0.178047 | 0.135141 | 2.430329 |
std | 1.073924 | 0.022001 | 1.054330 | 1.094879 | 1.158601 | 0.114889 | 6.762043 | 0.113332 | 0.150657 | 0.179226 | 5.347044e-15 | 0.404740 | 0.258871 | 0.213019 | 0.137888 | 0.098270 | 0.114361 | 0.537645 |
min | 2.523000 | 0.026000 | 2.596000 | 2.449000 | 6.635000 | 0.463000 | 48.478000 | 0.382000 | -0.288000 | 0.082000 | 2.430000e+00 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.648000 |
25% | 4.852000 | 0.043000 | 4.991000 | 4.706000 | 8.541000 | 0.750000 | 59.802000 | 0.718000 | -0.126000 | 0.667000 | 2.430000e+00 | 0.666000 | 0.647000 | 0.357000 | 0.409000 | 0.105000 | 0.060000 | 2.138000 |
50% | 5.534000 | 0.054000 | 5.625000 | 5.413000 | 9.569000 | 0.832000 | 66.603000 | 0.804000 | -0.036000 | 0.781000 | 2.430000e+00 | 1.025000 | 0.832000 | 0.571000 | 0.514000 | 0.164000 | 0.101000 | 2.509000 |
75% | 6.255000 | 0.070000 | 6.344000 | 6.128000 | 10.421000 | 0.905000 | 69.600000 | 0.877000 | 0.079000 | 0.845000 | 2.430000e+00 | 1.323000 | 0.996000 | 0.665000 | 0.603000 | 0.239000 | 0.174000 | 2.794000 |
max | 7.842000 | 0.173000 | 7.904000 | 7.780000 | 11.647000 | 0.983000 | 76.953000 | 0.970000 | 0.542000 | 0.939000 | 2.430000e+00 | 1.751000 | 1.172000 | 0.897000 | 0.716000 | 0.541000 | 0.547000 | 3.482000 |
The highest Index recorded is 7.8, the lowest is 2.52.
I'll start by plotting a world map to get a sense of the Index's global distribution.
# geojson information found in https://geojson-maps.ash.ms/
# Change some countries names in order to match the geojson data
data = df21.copy()
data.loc[data.Country == 'Czech Republic', 'Country'] = "Czech Rep."
data.loc[data.Country == 'Czech Republic', 'Country'] = "Czech Rep."
data.loc[data.Country == 'Taiwan Province of China', 'Country'] = "Taiwan"
data.loc[data.Country == 'South Korea', 'Country'] = 'Korea'
data.loc[data.Country == 'Bosnia and Herzegovina', 'Country'] = "Bosnia and Herz."
data.loc[data.Country == 'Dominican Republic', 'Country'] = "Dominican Rep."
data.loc[data.Country == 'North Cyprus', 'Country'] = "Cyprus"
data.loc[data.Country == 'Congo (Brazzaville)', 'Country'] = "Congo"
data.loc[data.Country == 'Ivory Coast', 'Country'] = "Côte d'Ivoire"
data.loc[data.Country == 'North Macedonia', 'Country'] = "Macedonia"
data.loc[data.Country == 'Laos', 'Country'] = "Lao PDR"
data.loc[data.Country == 'Palestinian Territories', 'Country'] = 'Palestine'
# No in geo_word: 'Bahrain', 'Malta', 'Singapore', 'Mauritius', 'Hong Kong S.A.R. of China', 'Maldives', 'Comoros'
# Creating the necesary geojson file
# https://towardsdatascience.com/how-to-create-outstanding-custom-choropleth-maps-with-plotly-and-dash-49ac918a5f05
import json
# Loading geojson from (DATA_PATH depending on your local settings)
with open('custom.geo.json') as f:
geo_world = json.load(f)
# Instanciating necessary lists
found = []
missing = []
countries_geo = []
# For simpler acces, setting "zone" as index in a temporary dataFrame
tmp = data.set_index('Country')
# Looping over the custom GeoJSON file
for country in geo_world['features']:
# Country name detection
country_name = country['properties']['name']
# Checking if that country is in the dataset
if country_name in tmp.index:
# Adding country to our "Matched/found" countries
found.append(country_name)
# Getting information from both GeoJSON file and dataFrame
geometry = country['geometry']
# Adding 'id' information for further match between map and data
countries_geo.append({
'type': 'Feature',
'geometry': geometry,
'id':country_name
})
# Else, adding the country to the missing countries
else:
missing.append(country_name)
# Displaying metrics
#print(f'Countries found: {len(found)} out of 149')
geo_world_ok = {'type': 'FeatureCollection', 'features': countries_geo}
# Create figure
fig = px.choropleth_mapbox(
data,
geojson=geo_world_ok,
locations='Country',
color=data['Ladder score'],
color_continuous_scale=['#c0630d', '#e29655', '#fff8c2','#84b3bb','#2a6a99'],
range_color=(3, 8),
mapbox_style='open-street-map', #there are more in mapbox
zoom=0.35,
center={'lat': 30, 'lon': 0},
opacity=0.85,
title='Happines Index 2021 - World View',
labels={'Ladder score':'Happines Index'},
height=400, #width=800
)
fig.update_layout(margin={"r":0,"t":15,"l":15,"b":15},
paper_bgcolor='#f2f2f2',
title_font_family='Arial',
title_font_color='#323232',
title_font_size=20,
title_x=0.025,
title_y=0.94,
#legend_font_family='Arial',
)
# Display figure
fig.show()
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
ax.set_frame_on(False)
# plots
regional_order = df21.groupby('Regional indicator')['Ladder score'].mean().sort_values(ascending=False).index
palette = ['lightgray' for i in regional_order]
palette[0] = palette[1] = high_c
palette[-1] = palette[-2] = low_c
color_text = ['gray' for i in regional_order]
color_text[0] = color_text[1] = color_text[-1] = color_text[-2] = 'white'
sns.barplot(x='Regional indicator', y='Ladder score', data=df21,
ci=95,
order=regional_order,
palette=palette,
edgecolor='lightgray',
errwidth=1.5,
#errcolor='gray'
)
ax.axhline(y=data['Ladder score'].mean(), xmax=10, color='#362a22', linewidth=0.9, linestyle='--', alpha=0.4,)
for i in range(len(regional_order)):
ax.annotate(regional_order[i], xy=(0.2+i, 0.25), fontweight='bold',
fontfamily='sans serif',color=color_text[i], fontsize=8,rotation=90)
# title
plt.title('Happines Index Mean by region', pad=29, loc='left', color='#191919',
fontfamily='sans serif', fontweight='bold', fontsize = 20, weight='bold', alpha=0.9)
ax.text(-0.48, 7.92, 'North America and Europe at the Top',
fontsize=13, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.text(0.61, 0.08,'Source: The World Happines Report (2021)', ha='left',
fontsize=10, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
# Axis
ax.axes.get_xaxis().set_ticks([]) # errase the ticks on x ax
ax.set_xlabel(None)
ax.axes.get_yaxis().set_ticks([]) # errase the ticks on y ax
ax.set_ylabel(None)
fig.show()
North America and Western Europe have the highest happiness indexes, whereas Sub-Saharan Africa and South Asia have the lowest.
The confidence intervals show that almost all Latin American and Caribbean countries have rates that are higher than the global average.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#9ba5a8'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
ax.set_frame_on(False)
# data from top and bottom -Included Colombia-
col = df21[df21['Country']=='Colombia']
top_bottom = df21.head(10).append([col, df21.tail(10)])
top_bottom['Rank']= top_bottom.index + 1
top_bottom.reset_index(drop=True, inplace=True)
# palette
pal = (sns.light_palette('lightgrey', 21)).as_hex()
pal[0] = pal[1] = pal[2] = low_c # color highlight
pal[-1] = pal[-2] = pal[-3] = high_c
pal[10] = neutral_c
pal = reversed(pal)
# plots
ax.axvline(x=df21['Ladder score'].mean(), color='#191919', linewidth=0.7, linestyle='--', alpha=0.5, ymax=0.48)
sns.barplot(x="Ladder score",y="Country",data=top_bottom,
palette=pal, ax=ax, edgecolor='darkgray', linewidth=0.2)
# Countries names
color_text = ['#474747' for _ in range(len(top_bottom))]
color_text[0] = color_text[1] = color_text[2] = color_text[10] = color_text[-1] = color_text[-2] = color_text[-3] = 'white'
for i in range(len(top_bottom)):
ax.annotate(str(top_bottom['Rank'][i])+'. '+top_bottom['Country'][i],
xy=(top_bottom['Ladder score'][i]-(top_bottom['Ladder score'][i]*0.01), i),
va = 'center', ha='right',fontweight='light',
fontfamily='sans serif',color=color_text[i], fontsize=8,rotation=0)
# Text and annotations
Xstart, Xend = ax.get_xlim()
Ystart, Yend = ax.get_ylim()
ax.text(Xstart, Yend-2.3, 'The Happiest & Unhappiest Countries in the World',
fontsize=16, fontweight='bold', fontfamily='sans serif',color='#191919')
ax.text(Xstart, Yend-1.1, 'Top and Bottom Ten Countries - Colombia Included -',
fontsize=12, fontweight='light', fontfamily='sans serif',color='#1e1e1e')
ax.text(6.55, Ystart,'Source: The World Happines Report (2021)', ha='left',
fontsize=9, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
ax.text(df21['Ladder score'].mean()-0.12, Ystart-.4, 'mean', alpha=0.7, rotation='vertical',
fontsize=7, fontfamily='sans serif',color='#191919')
ax.annotate('7 of the bottom 10\nare in Africa', xy=(4.3, Ystart-5), xytext=(5.4, Ystart-5),
fontsize=9, ha='center', va='center',fontfamily='sans serif',
bbox=dict(boxstyle='round', fc=low_c),
arrowprops=dict(arrowstyle='-[, widthB=7, lengthB=0.3', lw=1, color='gray'), color='white')
ax.annotate('9 of the top 10\nare in Europe', xy=(8, Yend+5), xytext=(9, Yend+5),
fontsize=9, ha='center', va='center',fontfamily='sans serif',
bbox=dict(boxstyle='round', fc=high_c),
arrowprops=dict(arrowstyle='-[, widthB=7, lengthB=0.3', lw=1, color='gray'), color='white')
# Ax
ax.axes.get_xaxis().set_ticks([]) # errase ticks on x
ax.tick_params(axis='x', labelsize=8, colors='grey')
ax.set(xlim=(0, 9.2))
ax.set(xlabel=None) # errase xlabel
ax.axes.get_yaxis().set_ticks([]) # errase ticks on y
ax.set(ylabel=None) # errase ylabel
fig.show()
Despite the fact that South Asia and North America had the lowest and highest average rates in 2021, the countries at the top of the list are primarily European, while the countries at the bottom are mostly from Africa.
Colombia is ranked 52nd in the world, with a score that is higher than the global average.
Countries in North America and Western Europe are "happy," while those in South Asia are "sad." But what about the countries in the middle?
# list of region sorted by regions Ladder score mean
regions = df21.groupby('Regional indicator').mean().sort_values(by='Ladder score', ascending=False).index.tolist()
def countries_by_region(r):
countries_by_region = [df21[df21['Regional indicator']==region].sort_values(by='Ladder score', ascending=False).Country.tolist() for region in r]
return countries_by_region
def scores_by_region(r):
scores_by_region = [df21[df21['Regional indicator']==region].sort_values(by='Ladder score', ascending=False)['Ladder score'] for region in r]
return scores_by_region
# create the colormap
ladder_min = df21['Ladder score'].min()
ladder_max = df21['Ladder score'].max()
norm = matplotlib.colors.Normalize(vmin=ladder_min, vmax=ladder_max)
my_colors = ['#e09a67', '#e8b693', '#edd2c0', '#bec9d7', '#8da5c0', '#5a83aa'] # https://vis4.net/palettes/#/6|d|5a83aa,eeeeee|eeeeee,e09a67|1|1
my_cmap = ListedColormap(my_colors)
my_mapper = cm.ScalarMappable(norm=norm, cmap=my_cmap)
# titles on graph
regions_titles = ['North America\nand ANZ',
'Western\nEurope',
'Central and\nEastern Europe',
'Latin America\nand Caribbean',
'East Asia',
'Commonwealth of\nIndependent States',
'Southeast Asia',
'Middle East\nand North Africa',
'Sub-Saharan\nAfrica',
'South Asia']
# regions to cut from plot
cut_top=2
cut_bottom=-1
regions = regions[cut_top:cut_bottom]
countries_by_region = countries_by_region(regions)
scores_by_region = scores_by_region(regions)
regions_titles = regions_titles[cut_top:cut_bottom]
plots = {}
plot = 1
for reg in range(len(countries_by_region)):
plots[('24'+str(plot))] = {
'values': [1 for c in countries_by_region[reg]],
'colors': [my_mapper.to_rgba(s) for s in scores_by_region[reg]],
'starting_location': 'NW', # {'NW', 'SW', 'NE', 'SE'}
'vertical': True,
'plot_anchor':'N',
'interval_ratio_x': 0.1,
'interval_ratio_y': 0.1,
'title': {
'label': regions_titles[reg],
'loc': 'center',
'font': 'sans serif',
'color': '#404040',
'fontsize': 12,
'fontweight': 'semibold',
'alpha':0.8,
'fontdict': {
#'verticalalignment':'center',
},
#'verticalalignment':'center',
},
}
if plot == 4:
plot += 2
else:
plot +=1
# palette for 245
colors_plot245 = [background for _ in range(36)]
change = [1,7,13,19,25,31]
colors_plot245[33] = my_mapper.to_rgba(df21['Ladder score'].mean())
for i in change:
colors_plot245[i] = my_colors[i//6]
plots['245'] = {
'values': [1 for _ in range(36)],
'colors': colors_plot245,
'starting_location': 'SE', # {'NW', 'SW', 'NE', 'SE'}
'vertical': False,
'plot_anchor':'NE', #The alignment method of subplots. {'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W'}
#'block_aspect_ratio': 1,
'columns': 6,
'interval_ratio_x': 0.6,
'interval_ratio_y': 0.6,
'title': {
'label': '',
'loc': 'center',
'font': 'sans serif',
'color': '#404040',
'fontsize': 10,
'fontweight': 'medium',
'alpha':1
},
}
fig = plt.figure(
FigureClass=Waffle,
plots=plots,
columns=6,
figsize=(12, 10)
)
fig.set_facecolor(background)
# Annotations
fig.text(-0.01, 1.05, 'Countries in the Middle Section',
fontsize=24, fontweight='bold', fontfamily='sans serif',color='#191919')
fig.text(-0.01, 1.023, '''Countries on North America and Western Europe are happy, in South Asia are ‘sad’, what about countries in regions in between? ''',
fontsize=13.5, fontweight='light', fontfamily='sans serif',color='#191919')
fig.text(0.015, 0.605,'World mean', ha='left',
fontsize=11, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.text(0.015, 0.505,'1 square = 1 country\nBlue indicates more happines', ha='left',
fontsize=11, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.text(-0.01, 0.4,'Source: The World Happines Report (2021)', ha='left',
fontsize=14, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.subplots_adjust(hspace=-0.72)
fig.show()
from dominance_analysis import Dominance
dfvars = df21[['Ladder score', 'Logged GDP per capita', 'Social support', 'Healthy life expectancy',
'Freedom to make life choices', 'Perceptions of corruption', 'Generosity']]
dfvars = dfvars.rename(columns={'Ladder score': 'Happiness', 'Logged GDP per capita':'GDP PC',
'Social support':'Social Supp.', 'Healthy life expectancy':'Life Expec.',
'Freedom to make life choices':'Freedom', 'Perceptions of corruption':'Corruption'})
correlation = dfvars.corr()
dominance_regression = Dominance(data=dfvars,target='Happiness',objective=1)
incr_variable_rsquare = dominance_regression.incremental_rsquare()
variables = [key for key in incr_variable_rsquare]
importance = [incr_variable_rsquare[key]*100 for key in variables]
0%| | 0/6 [00:00<?, ?it/s]
Selecting 6 Best Predictors for the Model Selected Predictors : ['GDP PC', 'Social Supp.', 'Life Expec.', 'Freedom', 'Corruption', 'Generosity'] ******************** R-Squared of Complete Model : ******************** R Squared : 0.7558471374226855 Selecting 6 Best Predictors for the Model Selected Predictors : ['GDP PC', 'Social Supp.', 'Life Expec.', 'Freedom', 'Corruption', 'Generosity'] Creating models for 63 possible combinations of 6 features :
100%|██████████| 6/6 [00:00<00:00, 12.56it/s] 100%|██████████| 5/5 [00:00<00:00, 1297.74it/s]
######################### Model Training Done!!!!! ######################### ######################### Calculating Variable Dominances ######################### ######################### Variable Dominance Calculation Done!!!!! #########################
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
fig, (ax1, ax2) = plt.subplots(1,2, figsize = (15,5))
fig.patch.set_facecolor(background) # figure background color
# Ax1
ax1.set_facecolor(background)
my_colors = ['#e09a67', '#e8b693', '#edd2c0', '#bec9d7', '#8da5c0', '#5a83aa'] # https://vis4.net/palettes/#/6|d|5a83aa,eeeeee|eeeeee,e09a67|1|1
mask = ~np.tril(np.ones_like(correlation, dtype=np.bool))
sns.heatmap(correlation, ax=ax1, cmap=my_colors, annot=True, fmt='.2f',
linewidth=0.5, linecolor=background, square = True, mask=mask,
cbar_kws={'shrink': .8},
annot_kws={'size':10})
ax1.xaxis.set_tick_params(rotation=45, )
# Ax2
# colors
mini, maxi = min(importance), max(importance)
norm = matplotlib.colors.Normalize(vmax=maxi, vmin=mini)
colors = ['#bec9d7', '#8da5c0','#5a83aa']
my_cmap = ListedColormap(colors)
my_mapper = cm.ScalarMappable(norm=norm, cmap=my_cmap)
colors = [my_mapper.to_rgba(imp) for imp in importance]
bar = sns.barplot(x=importance, y=variables, ax=ax2, alpha=1,
palette=colors)
for imp in range(len(importance)):
ax2.annotate(str(round(importance[imp],1))+'%',
xy=(importance[imp]+3, imp),
va = 'center', ha='right',fontweight='medium',
fontfamily='sans serif',color='#191919', fontsize=10,rotation=0)
ax2.set_xticks([])
ax2.set_xlim(0,26)
ax2.set_ylim(7,-1)
ax2.set_frame_on(False)
fig.text(0.055, 1.15, 'Variables analysis',
fontsize=28, fontweight='bold', fontfamily='sans serif',color='#191919')
fig.text(0.07, 1.05, 'Correlation Matrix', alpha=0.9,
fontsize=20, fontweight='semibold', fontfamily='sans serif',color='#191919')
fig.text(0.07, 0.94, 'Happiness most strongly correlates with (1) wealth (GDP)\n(2) life expectancy, (3) social support, and (4) freedom', alpha=0.9,
fontsize=14, fontweight='regular', fontfamily='sans serif',color='#191919')
fig.text(0.53, 1.05, 'Variable Importance Estimates', alpha=0.9,
fontsize=20, fontweight='semibold', fontfamily='sans serif',color='#191919')
fig.text(0.53, 0.94, 'Top 3 Important factors: (1) GDP, (2) Social support\n(3) Life expectancy', alpha=0.9,
fontsize=14, fontweight='regular', fontfamily='sans serif',color='#191919')
fig.text(0.59, 0.18, 'Note: Calculated with incremental R2 contribution', alpha=0.9,
fontsize=12, fontweight='regular', fontfamily='sans serif',color='#191919')
fig.text(0.67, -0.07,'Source: The World Happines Report (2021)', ha='left',
fontsize=15, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.subplots_adjust(
#left=0.05,
wspace=0.6)
Per capita income, life expectancy, and social support are the variables with the highest estimated importance and are most correlated with the Happiness Index. Generosity does not appear to have relevance.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
col_c = '#fff8c2'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
palette = {'Western Europe':high_c,
'North America and ANZ':'#cccccc',
'Middle East and North Africa':'#cccccc',
'Latin America and Caribbean':neutral_c,
'Central and Eastern Europe':'#cccccc',
'East Asia':'#cccccc',
'Southeast Asia':'#cccccc',
'Commonwealth of Independent States':'#cccccc',
'Sub-Saharan Africa':low_c,
'South Asia':'#cccccc'
}
# Create new palette and change name for regions with #cccccc for _name in dataframe
data = df21.copy()
new_name = {region: '_' + region if color == '#cccccc' else region for region, color in palette.items()}
new_name['South Asia'] = 'Others'
data['Regional indicator'] = data['Regional indicator'].map(new_name)
new_palette = {new_name[region]: color for region, color in palette.items()}
# Plots
sns.scatterplot(data=data, x='Healthy life expectancy', y='Ladder score',
hue='Regional indicator',
palette=new_palette, alpha=0.95, ec='black',
size=data["Logged GDP per capita"] * 1000, legend=True, sizes=(5, 500))
sns.scatterplot(data=data[data['Country']=='Colombia'], x='Healthy life expectancy', y='Ladder score',
color=col_c, alpha=0.95,ec='black',
size=data["Logged GDP per capita"]*1000, linewidth=1,
legend=False, sizes=(5, 500))
# mean
Ystart, Yend = ax.get_ylim()
Xstart, Xend = ax.get_xlim()
ax.axvline(x=data['Healthy life expectancy'].mean(),ymax=Yend, color='#191919', linewidth=0.9, linestyle='--', alpha=0.4)
ax.axhline(y=data['Ladder score'].mean(), xmax=Xend, color='#191919', linewidth=0.9, linestyle='--', alpha=0.4,)
ax.text(data['Healthy life expectancy'].mean()-0.4, Ystart+0.2, 'mean', alpha=0.7, rotation='vertical',
fontsize=7, fontfamily='sans serif',color='#191919')
ax.text(Xstart+0.2, data['Ladder score'].mean()+.05, 'mean', alpha=0.7, #rotation='vertical',
fontsize=7, fontfamily='sans serif',color='#191919')
# Axes
ax.set_xlabel(" Healthy Life Expectancy",fontfamily='sans serif',loc='left',color='#191919')
ax.set_ylabel("Happiness Index Score",fontfamily='sans serif',loc='top',color='#191919')
ax.tick_params(axis = 'both', which = 'major', labelsize = 10)
for s in ["top","right","left"]:
ax.spines[s].set_visible(False)
ax.tick_params(axis='both', which='both',left=False, bottom=False,labelbottom=True)
# Text
ax.text(45,9.2,'Happiness Score, Life Expectancy, and GDP per Capita',
fontfamily='sans serif',fontweight='bold',fontsize=22,weight='bold',color='#191919')
ax.text(45,8.75,'Regional Comparison: Europe, Africa and Latin America'
,fontfamily='sans serif',fontweight='light',fontsize=16,color='#1e1e1e')
ax.text(79, 1.5,'Source: The World Happines Report (2021)', ha='left',
fontsize=12, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
# Legend
handles, labels = ax.get_legend_handles_labels()
col_label = Line2D([0], [0], marker='o', color=background, label='Colombia', markerfacecolor=col_c ,markersize=9)
handles.insert(4, col_label)
L = ax.legend(handles=handles, frameon=False,loc="upper center", bbox_to_anchor=(1.25, 1), ncol= 1, fontsize=12)
plt.setp(L.texts, family='sans serif')
L.get_texts()[6].set_text('GDP p/Capita [log]')
plt.show()
We can see a strong linear relationship between the happiness index, life expectancy, and per capita income. The happiest countries are those that are richest and have a higher life expectancy.
Most of the Latin American and Caribbean countries are positioned above the world average. Colombia occupies an intermediate position compared to its neighbors.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
col_c = '#fff8c2'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
palette = {'Western Europe':high_c,
'North America and ANZ':'#cccccc',
'Middle East and North Africa':'#cccccc',
'Latin America and Caribbean':neutral_c,
'Central and Eastern Europe':'#cccccc',
'East Asia':'#cccccc',
'Southeast Asia':'#cccccc',
'Commonwealth of Independent States':'#cccccc',
'Sub-Saharan Africa':low_c,
'South Asia':'#cccccc'
}
# Create new palette and change name for regions with #cccccc for _name in dataframe
data = df21.copy()
new_name = {region: '_' + region if color == '#cccccc' else region for region, color in palette.items()}
new_name['South Asia'] = 'Others'
data['Regional indicator'] = data['Regional indicator'].map(new_name)
new_palette = {new_name[region]: color for region, color in palette.items()}
# Plots
sns.scatterplot(data=data, x='Perceptions of corruption', y='Social support',
hue='Regional indicator',
palette=new_palette, alpha=0.95, ec='black',
size=data['Ladder score'], legend=True, sizes=(2, 500))
sns.scatterplot(data=data[data['Country']=='Colombia'], x='Perceptions of corruption', y='Social support',
color=col_c, alpha=0.95,ec='black',
size=data['Ladder score'], linewidth=1,
legend=False, sizes=(2, 500))
# mean
Ystart, Yend = ax.get_ylim()
Xstart, Xend = ax.get_xlim()
ax.axvline(x=data['Perceptions of corruption'].mean(),ymax=Yend, color='#191919', linewidth=0.9, linestyle='--', alpha=0.4)
ax.axhline(y=data['Social support'].mean(), xmax=Xend, color='#191919', linewidth=0.9, linestyle='--', alpha=0.4,)
ax.text(data['Perceptions of corruption'].mean()-0.01, Ystart+0.01, 'mean', alpha=0.7, rotation='vertical',
fontsize=7, fontfamily='sans serif',color='#191919')
ax.text(Xstart+0.01, data['Social support'].mean()+.005, 'mean', alpha=0.7,
fontsize=7, fontfamily='sans serif',color='#191919')
# Axes
ax.set_xlabel('Perceptions of corruption',fontfamily='sans serif',loc='left',color='#191919')
ax.set_ylabel('Social support',fontfamily='sans serif',loc='top',color='#191919')
ax.tick_params(axis = 'both', which = 'major', labelsize = 10)
for s in ["top","right","left"]:
ax.spines[s].set_visible(False)
ax.tick_params(axis='both', which='both',left=False, bottom=False,labelbottom=True)
# Text
ax.text(-0.01,1.115,'Corruption, Social Support and Happines Index',
fontfamily='sans serif',fontweight='bold',fontsize=23,weight='bold',color='#191919')
ax.text(-0.01,1.07,'Regional Comparison: Europe, Latin America and Africa'
,fontfamily='sans serif',fontweight='light',fontsize=17,color='#1e1e1e')
ax.text(1, 0.37,'Source: The World Happines Report (2021)', ha='left',
fontsize=12, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
ax.text(0.1,0.7,
'''
It appears that low level of corruption
are highly correlated with high levels
of social support
''',fontfamily='sans serif',fontsize=10,color='#302823')
# Legend
handles, labels = ax.get_legend_handles_labels()
col_label = Line2D([0], [0], marker='o', color=background, label='Colombia', markerfacecolor=col_c ,markersize=9)
handles.insert(4, col_label)
L = ax.legend(handles=handles, frameon=False,loc="upper center", bbox_to_anchor=(1.25, 1), ncol= 1, fontsize=12)
plt.setp(L.texts, family='sans serif')
L.get_texts()[6].set_text('Happines Index')
plt.show()
Countries with low perceptions of corruption have the highest levels of social support and are also the happiest, with the exception of Rwanda. Low levels of social support and a high perception of corruption characterize the saddest.
Colombia is one of the Latin American countries with the most negative perceptions of corruption.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
col_c = '#fff8c2'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
palette = {'Western Europe':high_c,
'North America and ANZ':'#cccccc',
'Middle East and North Africa':'#cccccc',
'Latin America and Caribbean':neutral_c,
'Central and Eastern Europe':'#cccccc',
'East Asia':'#cccccc',
'Southeast Asia':'#cccccc',
'Commonwealth of Independent States':'#cccccc',
'Sub-Saharan Africa':low_c,
'South Asia':'#cccccc'
}
# Create new palette and change name for regions with #cccccc for _name in dataframe
data = df21.copy()
new_name = {region: '_' + region if color == '#cccccc' else region for region, color in palette.items()}
new_name['South Asia'] = 'Others'
data['Regional indicator'] = data['Regional indicator'].map(new_name)
new_palette = {new_name[region]: color for region, color in palette.items()}
# Plots
#sns.regplot(data=data, x='Freedom to make life choices', y='Social support', scatter=False, order=2,
# line_kws={'lw':0.6, 'color': 'gray', 'linestyle':'--'}
# )
sns.scatterplot(data=data, x='Freedom to make life choices', y='Social support',
hue='Regional indicator',
palette=new_palette, alpha=0.95, ec='black',
size=data['Ladder score'], legend=True, sizes=(2, 500))
sns.scatterplot(data=data[data['Country']=='Colombia'], x='Freedom to make life choices', y='Social support',
color=col_c, alpha=0.95,ec='black',
size=data['Ladder score'], linewidth=1,
legend=False, sizes=(2, 500))
# mean
Ystart, Yend = ax.get_ylim()
Xstart, Xend = ax.get_xlim()
ax.axvline(x=data['Freedom to make life choices'].mean(),ymax=Yend, color='#191919', linewidth=0.9, linestyle='--', alpha=0.4)
ax.axhline(y=data['Social support'].mean(), xmax=Xend, color='#191919', linewidth=0.9, linestyle='--', alpha=0.4,)
ax.text(data['Freedom to make life choices'].mean()-0.01, Ystart+0.01, 'mean', alpha=0.7, rotation='vertical',
fontsize=7, fontfamily='sans serif',color='#191919')
ax.text(Xstart+0.01, data['Social support'].mean()+.005, 'mean', alpha=0.7, #rotation='vertical',
fontsize=7, fontfamily='sans serif',color='#191919')
# Axes
ax.set_xlabel('Freedom to make life choices',fontfamily='sans serif',loc='left',color='#1e1e1e')
ax.set_ylabel('Social support',fontfamily='sans serif',loc='top',color='#1e1e1e')
ax.tick_params(axis = 'both', which = 'major', labelsize = 10)
for s in ["top","right","left"]:
ax.spines[s].set_visible(False)
ax.tick_params(axis='both', which='both',left=False, bottom=False,labelbottom=True)
# Text
ax.text(0.3, 1.106,'Freedom, Social Support and Happines Index',
fontfamily='sans serif',fontweight='bold',fontsize=22,weight='bold',color='#191919')
ax.text(0.3 ,1.06,'Regional Comparison: Europe, Latin America and Africa',
fontfamily='sans serif',fontweight='light',fontsize=18,color='#1e1e1e')
ax.text(1, 0.38,'Source: The World Happines Report (2021)', ha='left',
fontsize=12, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
# Legend
handles, labels = ax.get_legend_handles_labels()
col_label = Line2D([0], [0], marker='o', color=background, label='Colombia', markerfacecolor=col_c ,markersize=9)
handles.insert(4, col_label)
L = ax.legend(handles=handles, frameon=False,loc="upper center", bbox_to_anchor=(1.25, 1), ncol= 1, fontsize=12)
plt.setp(L.texts, family='sans serif')
L.get_texts()[6].set_text('Happines Index')
fig.show()
The happiness index (circle size), social support, and freedom to make decisions all have a strong linear relationship; countries with high registers are the happiest.
Colombia's social support and freedom to make life decisions are both higher than the global average; this is true for each of the Index's metrics.
Year 2021, a set back year
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#9ba5a8'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
ax.set_frame_on(False)
df11_21 = df08_21[df08_21['year'] >= 2011]
# plot
sns.lineplot(x='year', y='Ladder score', data= df11_21,
ci=95, color=high_c)
# Ax
ax.tick_params(axis='both', labelsize=12, colors='grey')
ax.set(xlabel=None) # errase xlabel
ax.set_xticks(np.arange(2011,2022,2))
ax.set_yticks(np.arange(4,7.5,.5))
ax.set(ylabel=None) # errase ylabel
#ax.set_ylim(3.5,7)
Xstart, Xend = ax.get_xlim()
Ystart, Yend = ax.get_ylim()
ax.text(Xstart-0.5, Yend+0.4, 'Global Happines Index Score Through Time',
fontsize=20, fontweight='bold', fontfamily='sans serif',color='#191919')
ax.text(Xstart-0.5, Yend+0.195, '2021, a Setback Year',
fontsize=15, fontweight='light', fontfamily='sans serif',color='#1e1e1e')
ax.text(Xend-4.4, Ystart-0.45,'Source: The World Happines Report (2021)', ha='left',
fontsize=11, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
ax.legend(labels=['Happines Index'], loc='lower center')
fig.show()
The worldwide happiness index, which had been rising in recent years, plummeted in 2021, owing to the COVID-19 Pandemic, most likely. It appears that it took approximately two years for it to have the largest adverse impact on the global population's happiness.
The recent broadening of the confidence interval shows that the impact was uneven across the sample of countries, with some experiencing strong increases in happiness while others had sharp drops. The latest was the one who dragged the mean down.
df19 = df08_21[df08_21.year==2019]
df19.set_index('Country', inplace=True)
temp = df21.copy()
temp['Score 2019'] = 0
temp.set_index('Country', inplace=True)
for country in df19.index:
temp.loc[country, 'Score 2019'] = temp.loc[country, 'Ladder score'] - df19.loc[country, 'Ladder score']
total =len(temp)
perc_negatives = round(len(temp[temp['Score 2019']<0])/total*100, 1)
perc_positives = round(len(temp[temp['Score 2019']>0])/total*100, 1)
perc_equal = round(100-perc_negatives-perc_positives, 1)
change = pd.DataFrame({'Decrease': [perc_negatives],
'Increase': [perc_positives],
'Equal': [perc_equal]},
index=['Change 2019-2021'])
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
ax.set_frame_on(False)
change.plot(kind='barh', stacked=True, color=[low_c, high_c, neutral_c], ax=ax, figsize=(10, 2),
legend=True, xlim=(-2, 102), edgecolor='lightgrey')
ax.set_yticks([])
ax.set_xticks([])
ax.legend(loc='upper left', frameon=False,
borderpad = 0, bbox_to_anchor = (0.01, 1.2), ncol = 3, fontsize=10)
ax.text(-2, 1, 'Change in Hapinness 2019 - 2021',
fontsize=15, fontweight='bold', fontfamily='sans serif',color='#191919')
ax.text(-2, 0.84, 'Most of Countries Reduced Their Happiness',
fontsize=13, fontweight='light', fontfamily='sans serif',color='#1e1e1e')
ax.text(62, -0.45,'Source: The World Happines Report (2021)', ha='left',
fontsize=10.5, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
plt.figtext(0.28, 0.465, str(perc_negatives)+'%', fontsize = 10, fontname = 'sans serif', fontweight='semibold', color = 'white')
plt.figtext(0.69, 0.465, str(perc_positives)+'%', fontsize = 10, fontname = 'sans serif', fontweight='semibold', color = 'white')
plt.figtext(0.842, 0.465, str(perc_equal)+'%', fontsize = 10, fontname = 'sans serif', fontweight='semibold', color = 'white')
fig.show()
51.7% of the countries reached a lower level of happiness in 2021 compared to 2019. 41.6% improved their measurement and 6.7% remained at the same level.
Despite the pandemic, all of the index's indicators are better than they were ten years ago.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#fff8c2'
fig = plt.figure(figsize=(12, 6), dpi=150,facecolor=background)
gs = fig.add_gridspec(2, 3)
gs.update(wspace=0.2, hspace=0.3)
plot = 0
for row in range(0, 2):
for col in range(0, 3):
locals()["ax"+str(plot)] = fig.add_subplot(gs[row, col])
locals()["ax"+str(plot)].set_facecolor('#f5f5f5')
locals()["ax"+str(plot)].tick_params(axis='y', left=False)
locals()["ax"+str(plot)].get_yaxis().set_visible(False)
locals()["ax"+str(plot)].set_axisbelow(True)
for s in ["top","right","left"]:
locals()["ax"+str(plot)].spines[s].set_visible(False)
plot += 1
# Rename columns in dfh
tempdfh = dfh.rename(columns={'Log GDP per capita': 'Logged GDP per capita',
'Healthy life expectancy at birth': 'Healthy life expectancy'})
# Variables to plot
variables = ['Logged GDP per capita',
'Social support',
'Healthy life expectancy',
'Freedom to make life choices',
'Generosity',
'Perceptions of corruption']
plot = 0
for variable in variables:
sns.kdeplot(tempdfh.query("year == 2011")[variable], ax=locals()["ax"+str(plot)],
color = low_c, shade = True, label = '2011', alpha = 0.7)
locals()["ax"+str(plot)].axvline(tempdfh.query("year == 2011")[variable].mean(), linestyle = '--', color = low_c)
sns.kdeplot(df21[variable], ax=locals()["ax"+str(plot)],
color = high_c, shade = True, label = '2021', alpha = 0.5)
locals()["ax"+str(plot)].axvline(df21[variable].mean(), linestyle = '--', color = high_c)
locals()["ax"+str(plot)].axvline(tempdfh.query("year == 2020")[variable].mean(), ymax=0.05, linewidth= 2, linestyle = '--', color = neutral_c)
Xstart, Xend = locals()["ax"+str(plot)].get_xlim()
Ystart, Yend = locals()["ax"+str(plot)].get_ylim()
# annotations
locals()["ax"+str(plot)].text(Xend, Yend*(4/5),
str(round(df21[variable].mean()*100/tempdfh.query("year == 2011")[variable].mean()-100, 1)) + '%',
ha='right', fontname = 'sans serif', fontsize = 10, color ='#362a22')
# grid and ax
locals()["ax"+str(plot)].grid(which='major', axis='x', zorder=0, color='gray', linestyle=':', dashes=(1,5))
locals()["ax"+str(plot)].set_xlabel(variable, fontfamily='sans serif')
plot += 1
fig.text(0.11, 0.96,'Global Dynamics of all WHR Metrics 2011-2021',
fontfamily='sans serif',fontweight='bold',fontsize=18,weight='bold',color='#191919')
fig.text(0.66, -0.02,'Source: The World Happines Report (2021)', ha='left',
fontsize=12, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
leg = ax1.legend(['Mean', 'Mean', 'Mean 2020','2011', '2021'], loc=3, bbox_to_anchor = (1.4, 1.12), ncol = 2,
borderpad = -1.2, frameon = False, fontsize = 10)
for line in leg.get_lines():
line.set_linewidth(2)
fig.show()
When we compare the median for the years 2020 and 2021, we can see a drop in each of the metrics linked to the happiness index.
However, if we look at the last ten years, between 2011 and 2021, the metrics have improved (an improvement in perception of corruption is represented by a decrease in its metric), which appears to indicate that, despite the negative effects of the pandemic, there are now higher levels of per capita income, social support, life expectancy, and personal liberty.
# Reduced list as too many to show all at once and adding Colombia
top_bottom = dfh.groupby('Country')['Ladder score'].mean().sort_values(
ascending=False).sort_values(ascending=False).reset_index()
colombia = top_bottom[top_bottom['Country']=='Colombia']
top_bottom_historic = (top_bottom[:10].append([top_bottom[-10:],colombia])).sort_values(by='Ladder score',ascending=True)
top_bottom_historic['Rank'] = top_bottom_historic.index + 1
top_bottom_historic.reset_index(drop=True, inplace=True)
background = '#eeeeee'
high_c = '#5a83aa'
neutral_c = '#98b09d' #'#d88546' #'#8fc961' green
low_c = '#e09a67'
fig, ax = plt.subplots(1,1, figsize=(10, 5),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.set_facecolor(background)
# Plots
plot = 1
for country in top_bottom_historic['Country']:
# countries means
mean = dfh[dfh['Country'] == country].groupby('Country')['Ladder score'].mean()
# historic scores
sns.scatterplot(data=dfh[dfh['Country'] == country], y=plot, x='Ladder score',color='grey',s=50,ax=ax)
# mean score
sns.scatterplot(data=dfh[dfh['Country'] == country], y=plot, x=mean,color=low_c,ec='black',linewidth=1,s=75,ax=ax)
#2021 score
sns.scatterplot(data=df21[df21['Country'] == country], y=plot, x='Ladder score',color=high_c,ec='black',linewidth=1,s=75,ax=ax)
plot += 1
# rename Central African Republic for graphing purposes
top_bottom_historic.iloc[1, df21.columns.get_loc('Country')] = 'C.Africa Rep'
# Axes
ax.set_yticks(top_bottom_historic.index+1)
ax.set_yticklabels(top_bottom_historic['Country'], fontdict={'horizontalalignment': 'right', 'fontsize': 8}, alpha=0.7)
ax.tick_params(axis=u'both', which=u'both',length=0)
ax.set_xlabel('Happiness Index Score',fontfamily='sans serif',loc='left',color='#1e1e1e')
for s in ['top','right','bottom','left']:
ax.spines[s].set_visible(False)
Xstart, Xend = ax.get_xlim()
Ystart, Yend = ax.get_ylim()
ax.hlines(y=top_bottom_historic.index+1, xmin=Xstart, xmax=Xend, color='gray', alpha=0.5, linewidth=.3, linestyles='--')
ax.set_axisbelow(True)
# Title
ax.text(1, Yend+1.8, 'Happiness Index Scores Through the Years (2007-2021)',
fontsize=18, fontweight='bold', fontfamily='sans serif',color='#191919')
ax.text(1, Yend+0.3,'Top and Bottom Ten Countries - Colombia included -',
fontsize=14, fontweight='light', fontfamily='sans serif',color='#1e1e1e')
ax.text(5.77, Ystart-2.7,'Source: The World Happines Report (2021)', ha='left',
fontsize=10.5, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
# Annotations
plt.annotate('2021\nscore', xy=(6.05, 10.5), xytext=(6.8, 4.5),
arrowprops=dict(
color=high_c,
arrowstyle="->",
connectionstyle="arc3,rad=-.3"
),
fontsize=10,fontfamily='sans serif',ha='center', color=high_c)
plt.annotate('Mean\nscore', xy=(6.25, 10.5), xytext=(6.8, 7),
arrowprops=dict(
color=low_c,
arrowstyle="->",
connectionstyle="arc3,rad=-.5"
),
fontsize=10,fontfamily='sans serif',ha='center', color=low_c)
fig.show()
When we look at the top ten countries in terms of happiness, we can see that they tend to be consistent over time, even though they are close to the lowest levels that have been recorded since 2007, with the exception of Canada, which is behind and Finland, which has one of the highest indices.
The countries with lower time indices have more variability in their results. Afghanistan is the country with the lowest score, ranking second lowest since 2007, only ahead of its own score from the previous year.
Since 2007, the bottom half of the table has been dominated by African countries, while the top half has been dominated by European countries. This shows that the 2021 results, rather than being based on chance, appear to be adapting to a pattern over time.
Colombia also demonstrates consistency through time, drawing attention to the fact that the year 2021 saw one of the lowest figures ever recorded.
years = sorted(df08_21.year.unique())
countries_in_data = len(df08_21['Country'].unique())
lasts3 = [list(df08_21[df08_21['year']==year].sort_values(by='Ladder score').head(3).Country) for year in years]
differents_lasts3 = len(set([x for l in lasts3 for x in l]))
firsts3 = [list(df08_21[df08_21['year']==year].sort_values(by='Ladder score').tail(3).Country) for year in years]
differents_firsts3 = len(set([x for l in firsts3 for x in l]))
fig = plt.figure(figsize=(12, 4),dpi=150,facecolor=background,
FigureClass=Waffle,
rows=11,
values=[differents_firsts3, countries_in_data-differents_firsts3-differents_lasts3, differents_lasts3],
colors=[high_c, "lightgray", low_c],
icons=['chevron-circle-up', 'circle', 'chevron-circle-down'],
font_size=20,
vertical=True,
starting_location= 'NW',
)
fig.text(0.01, 1.08,'Top Leaderboard Concentration',
fontfamily='sans serif',fontweight='bold',fontsize=15,weight='bold',color='#191919')
fig.text(0.01, 0.99,'''
Since 2005 there have only ever been 11 different countries, out of 166 in the report,
to be on the top 3. In the bottom 3 there have been 22 countries.''',
fontsize=9, fontweight='light', fontfamily='sans serif',color='#474747')
fig.text(0.28, 0.04,'Source: The World Happines Report (2021)', ha='left',
fontsize=8, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.show()
Since 2005, only 11 countries have occupied the top three spots in the ranking, implying a concentration at the top. The bottom three spots are occupied by 22 countries.
df2011 = dfh[dfh.year == 2011]
df2011['Regional indicator'] = 'u'
for i in range(len(df2011)):
for j in range(len(df21)):
if df2011.iloc[i,0] == df21.iloc[j,0]:
df2011.iloc[i,11] = df21.iloc[j,1]
index_regional_21 = df21.groupby('Regional indicator').agg({'Ladder score': 'mean'}).reset_index()
index_regional_21['year'] = 2021
index_regional_11 = df2011[df2011['Regional indicator'] != 'u'].groupby('Regional indicator').agg({'Ladder score': 'mean'}).reset_index()
index_regional_11['year'] = 2011
index_regional_dynamics = pd.concat([index_regional_11, index_regional_21], ignore_index = True)
latinamerica_11 = df2011[df2011['Regional indicator'] == 'Latin America and Caribbean'][['Country', 'Ladder score', 'year']].reset_index(drop=True)
latinamerica_21 = df21[df21['Regional indicator'] == 'Latin America and Caribbean'][['Country', 'Ladder score']].reset_index(drop=True)
latinamerica_21['year'] = 2021
latinamerica_dynamics = pd.concat([latinamerica_11, latinamerica_21], ignore_index = True)
to_drop = ['Haiti', 'Uruguay', 'Bolivia','Dominican Republic', 'Nicaragua']
latinamerica_dynamics = latinamerica_dynamics[~latinamerica_dynamics['Country'].isin(to_drop)].reset_index(drop=True)
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
fig, (ax1, ax2) = plt.subplots(1,2, figsize = (15,15))
fig.patch.set_facecolor(background) # figure background color
# Ax1
ax1.set_facecolor(background)
regions = index_regional_21['Regional indicator'].to_list()
labels = ['Central and\nEastern Europe',
'Commonwealth of\nIndependent States',
'East Asia',
'Latin America\nand Caribbean',
'Middle East\nand North Africa',
'North America\nand ANZ',
'South Asia\n',
'Southeast Asia',
'Sub-Saharan Africa',
'Western Europe']
for region in range (len(regions)):
reg = index_regional_dynamics[index_regional_dynamics['Regional indicator'] == regions[region]]
reg.index = range(2)
color = high_c if reg.iloc[1,1] > reg.iloc[0,1] else low_c
ax1.plot(reg['year'], reg['Ladder score'], marker = 'o', markersize = 7, linewidth = 3, color = color)
ax1.text(reg['year'].values[0]-0.4, reg['Ladder score'].values[0]-0.015, labels[region], ha = 'right', fontname = 'sans serif', fontsize = 11)
ax1.text(reg['year'].values[1]+1.9, reg['Ladder score'].values[1]-0.015,
str(round((reg.iloc[1,1]*100/reg.iloc[0,1]) - 100, 1)) + '%',
ha='right', fontname = 'sans serif', fontsize = 14, color = color)
ax1.vlines(x = 2011, ymin = 4.3, ymax = 7.5, color = 'black', alpha = 0.5, linewidth = 2, linestyles = ':')
ax1.vlines(x = 2021, ymin = 4.3, ymax = 7.5, color = 'black', alpha = 0.5, linewidth = 2, linestyles = ':')
for i in ['right', 'left', 'bottom',]:
ax1.spines[i].set_visible(False)
ax1.spines['top'].set_alpha(0.6)
ax1.tick_params(axis='y', labelsize=16, labelleft=True, pad=10)
ax1.set_ylim(4.2,7.5)
ax1.set_xlim(2005.5,2024)
ax1.set_xticks([2011, 2021])
ax1.tick_params(axis='x', labelsize=22)
ax1.grid(color = 'gray', linestyle = ':', axis = 'y', alpha = 0.7, zorder = 0, dashes = (1,7))
ax1.set_title('Regional Dynamic', fontdict={'fontsize':20, 'color':'#191919'}
, loc='left', y=1.0)
# Ax2
ax2.set_facecolor(background)
countries = set(latinamerica_dynamics['Country'].to_list())
for c in countries:
country = latinamerica_dynamics[latinamerica_dynamics['Country'] == c]
country.index = range(2)
color = high_c if country.iloc[1,1] > country.iloc[0,1] else low_c
ax2.plot(country['year'], country['Ladder score'], marker = 'o', markersize = 7, linewidth = 3, color = color)
ax2.text(country['year'].values[0]-0.3, country['Ladder score'].values[0]-0.015, c, ha = 'right', fontname = 'sans serif', fontsize = 11)
ax2.vlines(x = 2011, ymin = 4.3, ymax = 7.5, color = 'black', alpha = 0.5, linewidth = 2, linestyles = ':')
ax2.vlines(x = 2021, ymin = 4.3, ymax = 7.5, color = 'black', alpha = 0.5, linewidth = 2, linestyles = ':')
for i in ['right', 'left', 'bottom']:
ax2.spines[i].set_visible(False)
ax2.spines['top'].set_alpha(0.6)
#ax2.spines['left'].set_linestyle('dashed')
ax2.set_xlim(2007,2023)
ax2.set_xticks([2011, 2021])
ax2.tick_params(axis='x', labelsize=22)
ax2.grid(color = 'gray', linestyle = ':', axis = 'y', alpha = 0.7, zorder = 0, dashes = (1,7))
ax2.tick_params(axis='y', direction='in', labelsize=16, labelleft=False, labelright=True, pad=0)
ax2.set_ylim(4.2,7.5)
ax2.set_title('Latin America & Caribbean', fontdict={'fontsize':20, 'color':'#1e1e1e', }
, loc='left', y=1.0)
fig.text(0.02,0.917, 'Changes in the Happy Index 2011-2021', color = '#1e1e1e',
fontweight='bold', fontsize = 28, fontname = 'sans serif')
fig.text(0.63, 0.07,'Source: The World Happines Report (2021)', ha='left',
fontsize=18, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.subplots_adjust(
left=0.05,
wspace=0.25)
fig.show()
In comparison to 2011, the regions that are the happiest today are Europe, Sub-Saharan Africa, and the Independent States; this last has had the greatest increase in happiness levels (7.4 percent ). The remainder of the world's regions have lost ground, including North America, which remains in first place.
Latin America and the Caribbean have had a -2.3 percent decline in their rankings during the last decade. This decline is being caused by a drop in Latin American countries, while in the Caribbean has increased. Costa Rica is the happiest country in the region in 2021.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
col_c = '#fff8c2'
fig = plt.figure(figsize=(10, 4), dpi=150,facecolor=background)
gs = fig.add_gridspec(1, 1)
gs.update(wspace=0, hspace=0)
ax0 = fig.add_subplot(gs[0, 0])
ax0.set_facecolor(background)
for s in ["right", "top"]:
ax0.spines[s].set_visible(False)
ax0.set_xlabel("Year",fontfamily='sans serif',loc='left',color='#1e1e1e')
ax0.set_ylabel("Happiness Index Score",fontfamily='sans serif',loc='top',color='#1e1e1e')
ax0.tick_params(axis = 'both', which = 'major', labelsize = 10)
ax0.tick_params(axis='both', which='both', left=False, bottom=False,labelbottom=True)
# plots
# lows and highs
highs = list(df21.iloc[1:4,0])
lows = list(df21.iloc[-4:-1,0])
lh = lows + highs
for countrie in lh:
sns.lineplot(ax=ax0,data=df08_21[(df08_21['Country']==countrie)], x='year', y='Ladder score',color='lightgray')
# highest:
sns.lineplot(ax=ax0,data=df08_21[(df08_21['Country']==df21.iloc[0,0])], x='year', y='Ladder score',color=high_c)
# lowest:
sns.lineplot(ax=ax0,data=df08_21[(df08_21['Country']==df21.iloc[-1,0])], x='year', y='Ladder score',color=low_c)
# Colombia
sns.lineplot(ax=ax0,data=df08_21[(df08_21['Country']=='Colombia')], x='year', y='Ladder score',color=neutral_c)
ax0.axhline(y=df08_21[(df08_21['Country']=='Colombia')]['Ladder score'].iloc[-1], xmax=0.84, color=neutral_c, linewidth=0.8, linestyle='--', alpha=0.6,)
Xstart, Xend = ax0.get_xlim()
Ystart, Yend = ax0.get_ylim()
# markers
for countrie in highs:
ax0.plot(2021,df08_21[(df08_21['Country']==countrie)]['Ladder score'].reset_index().iloc[-1,-1], 'ko', markersize=5, fillstyle='full',color=high_c, markeredgewidth=1.5)
for countrie in lows:
ax0.plot(2021,df08_21[(df08_21['Country']==countrie)]['Ladder score'].reset_index().iloc[-1,-1], 'ko', markersize=5, fillstyle='full',color=low_c, markeredgewidth=1.5)
# markers highest
ax0.plot(2021,df08_21[(df08_21['Country']==df21.iloc[0,0])]['Ladder score'].reset_index().iloc[-1,-1], 'ko', markersize=5, fillstyle='full',color=high_c, markeredgewidth=1.5)
# markers lowest
ax0.plot(2021,df08_21[(df08_21['Country']==df21.iloc[-1,0])]['Ladder score'].reset_index().iloc[-1,-1], 'ko', markersize=5, fillstyle='full',color=low_c, markeredgewidth=1.5)
# marker Colombia
ax0.plot(2021,df08_21[(df08_21['Country']=='Colombia')]['Ladder score'].reset_index().iloc[-1,-1], 'ko', markersize=5, fillstyle='full',color=neutral_c, markeredgewidth=1.5)
# names
for i in range(len(highs)):
ax0.text(2021.2,df08_21[(df08_21['Country']==highs[i])]['Ladder score'].reset_index().iloc[-1,-1]-0.3*(i),highs[i],color=high_c,fontfamily='monospace',fontsize=8, rotation=0)
for i in range(len(lows)):
ax0.text(2021.2,df08_21[(df08_21['Country']==lows[i])]['Ladder score'].reset_index().iloc[-1,-1]-0.2*(i),lows[i],color=low_c,fontfamily='monospace',fontsize=8, rotation=0)
# highest name
ax0.text(2021.2,df08_21[(df08_21['Country']==df21.iloc[0,0])]['Ladder score'].reset_index().iloc[-1,-1]+0.2,df21.iloc[0,0],color=high_c,fontfamily='monospace',fontsize=8, rotation=0)
# lowest name
ax0.text(2021.2,df08_21[(df08_21['Country']==df21.iloc[-1,0])]['Ladder score'].reset_index().iloc[-1,-1]-0.2,df21.iloc[-1,0],color=low_c,fontfamily='monospace',fontsize=8, rotation=0)
# Colombia name
ax0.text(2021.2,df08_21[(df08_21['Country']=='Colombia')]['Ladder score'].reset_index().iloc[-1,-1]-0.2,'Colombia',color=neutral_c,fontfamily='monospace',fontsize=8, rotation=0)
ax0.yaxis.set_ticks(np.arange(0, 10, 1))
ax0.set_xlim(left = 2011, right = 2023)
plt.xticks(fontname = 'sans serif')
plt.yticks(fontname = 'sans serif')
Xstart, Xend = ax0.get_xlim()
Ystart, Yend = ax0.get_ylim()
ax0.text(Xstart-.5, Yend+1.3, 'Changes over time 2011-2021', fontsize=18, fontweight='bold',
fontfamily='sans serif',color='#191919')
ax0.text(Xstart-.5, Yend+0.6, 'Top and Bottom Countries', fontsize=14, fontweight='light',
fontfamily='monospace',color='#1e1e1e')
ax0.text(Xend-4.1, Ystart-1.45,'Source: The World Happines Report (2021)', ha='left',
fontsize=10, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
fig.show()
The happiest countries appear to maintain their happiness through time, whilst the poorest countries appear to be becoming worse.
This graph confirms yet again that Colombia is currently at one of the lowest levels in recent years.
background = '#eeeeee'
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
fig = plt.figure(figsize=(12, 6), dpi=150,facecolor=background)
gs = fig.add_gridspec(2, 3)
gs.update(wspace=0.2, hspace=0.3)
plot = 0
for row in range(0, 2):
for col in range(0, 3):
locals()['ax'+str(plot)] = fig.add_subplot(gs[row, col])
locals()['ax'+str(plot)].set_facecolor('#f5f5f5')
for s in ['top','right']:
locals()['ax'+str(plot)].spines[s].set_visible(False)
plot += 1
# Rename columns in dfh
df08_21.rename(columns={'Healthy life expectancy at birth': 'Healthy life expectancy'},
inplace=True)
# Variables to plot
variables = ['Log GDP per capita',
'Social support',
'Healthy life expectancy',
'Freedom to make life choices',
'Generosity',
'Perceptions of corruption']
# Countries to plot
countries = ['Finland', 'Colombia', 'Afghanistan']
colors = {'Colombia': neutral_c, 'Finland': high_c, 'Afghanistan':low_c }
plot = 0
for variable in variables:
for countrie in countries:
sns.lineplot(x='year', y=variable, data=df08_21[df08_21['Country'] == countrie],
color=colors[countrie], ci=None, ax=locals()["ax"+str(plot)], linewidth=1)
sns.scatterplot(x='year', y=variable, data=df08_21[df08_21['Country'] == countrie],
color=colors[countrie], ci=None, ax=locals()["ax"+str(plot)], s=20)
locals()['ax'+str(plot)].set_xlabel(None)
locals()['ax'+str(plot)].set_yticks([])
locals()['ax'+str(plot)].set_xlim(2011,2021)
locals()['ax'+str(plot)].set_ylabel(variable.title(),fontfamily='sans serif', color='#1e1e1e', fontsize=12)
plot += 1
fig.text(0.1, 0.98,'Colombia, Findland and Afghanistan',
fontfamily='sans serif',fontweight='bold',fontsize=20,weight='bold',color='#191919')
fig.text(0.1, 0.93,'All WHR Metrics',
fontsize=14, fontweight='light', fontfamily='sans serif',color='#1e1e1e')
fig.text(0.642, 0.04,'Source: The World Happines Report (2021)', ha='left',
fontsize=12, fontweight='medium', fontfamily='sans serif',color='#1e1e1e')
leg = ax1.legend(['Finland', 'Colombia', 'Afghanistan'], loc=9 , ncol = 3,bbox_to_anchor = (1.4, 1.18)
, borderpad = 0, frameon = False, fontsize = 10)
for line in leg.get_lines():
line.set_linewidth(4)
fig.show()
Colombia is below Finland and ahead of Afghanistan in each of the index's metrics, with the exception of the generosity metric, which, after historically being behind both of these countries, repunted and moved ahead of Finland in 2020.
Finally, I'll use the K-means clustering approach to find groups of countries that share similar characteristics.
Clusters are defined as groups of data objects that are more comparable to other data objects in their cluster than to data objects in other clusters.
The clustering technique is a collection of techniques for dividing data into groups or clusters. It is the process of dividing a set of data into groups in which members of the same group share comparable characteristics. The goal of K-means is simple: group comparable data points and find subyacent patterns.
I'll use the Elbow Method to select the number of clusters.
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
dfkm_standarized = df21[['Country', 'Ladder score','Logged GDP per capita', 'Social support', 'Healthy life expectancy',
'Freedom to make life choices', 'Generosity', 'Perceptions of corruption']]
X = dfkm_standarized[['Ladder score','Logged GDP per capita', 'Social support', 'Healthy life expectancy',
'Freedom to make life choices', 'Generosity', 'Perceptions of corruption']]
X_standarized = StandardScaler().fit_transform(X)
wcss =[]
for i in range(1, 6):
km = KMeans(n_clusters = i, random_state = 0)
km.fit(X_standarized)
wcss.append(km.inertia_)
high_c = '#5a83aa'
fig, ax = plt.subplots(1,1, figsize=(3, 3),dpi=120)
fig.patch.set_facecolor(background) # figure background color
ax.plot(range(1, 6), wcss, color=high_c)
ax.scatter(x=3, y=wcss[2], c=high_c)
ax.set_facecolor(background)
for s in ['top','right']:
ax.spines[s].set_visible(False)
ax.tick_params(axis = 'both', which = 'major', labelsize = 12)
plt.title('The Elbow Method')
plt.xlabel('No. of clusters')
plt.ylabel('W.C.S.S')
fig.show()
To run the model, I'll choose k=3 clusters. This will categorize the countries reported into three groups based on common patrons found in their metrics.
kmeans = KMeans(n_clusters=3)
X['Cluster'] = kmeans.fit_predict(X_standarized)
X['Cluster'] = X['Cluster'].astype('category')
dfkm_standarized['Cluster'] = X['Cluster'].astype('category')
dfkm_standarized.groupby('Cluster').mean().sort_values(by='Ladder score')
Ladder score | Logged GDP per capita | Social support | Healthy life expectancy | Freedom to make life choices | Generosity | Perceptions of corruption | |
---|---|---|---|---|---|---|---|
Cluster | |||||||
1 | 4.467255 | 8.082404 | 0.685936 | 57.034340 | 0.723447 | 0.053106 | 0.764638 |
2 | 5.696132 | 9.799737 | 0.856342 | 67.457289 | 0.796197 | -0.083855 | 0.801658 |
0 | 6.981769 | 10.797923 | 0.926000 | 72.175346 | 0.901346 | 0.062385 | 0.443308 |
dfkm_standarized['Cluster'].value_counts()
2 76 1 47 0 26 Name: Cluster, dtype: int64
#fig = plt.figure(figsize=(5, 5),dpi=120)
fig, ax = plt.subplots(1,1, figsize=(5, 0.1),dpi=120)
fig.patch.set_facecolor(background) # figure background color
palette = {0:low_c,
1:high_c,
2:neutral_c}
# Plot
sns.set(rc={'axes.facecolor':background, 'axes.grid': False,
'axes.edgecolor': 'lightgray',
'figure.facecolor':background})
g = sns.JointGrid(data=dfkm_standarized, x='Healthy life expectancy', y='Ladder score', hue='Cluster',
ratio=7, height=8)
g.plot_joint(sns.scatterplot, alpha=.95, linewidth=0.1, ec='black',
palette=palette, legend=False, size=dfkm_standarized['Logged GDP per capita'] * 1000)
g.plot_marginals(sns.histplot, palette=palette, bins=15, alpha=.9, linewidth=0.1, edgecolor='black')
fig.text(0.01, 1,'K-means Clustering',
fontfamily='sans serif',fontweight='bold',fontsize=14,weight='bold',color='#191919')
fig.text(0.01, -1,'Happines and Life Expectancy',
fontsize=10, fontweight='light', fontfamily='sans serif',color='#1e1e1e')
for s in ['top','right', 'left', 'bottom']:
ax.spines[s].set_visible(False)
ax.set_yticks([])
ax.set_xticks([])
fig.show()
high_c = '#5a83aa'
low_c = '#e09a67'
neutral_c = '#98b09d'
# Create figure
fig = px.choropleth_mapbox(
dfkm_standarized,
geojson=geo_world_ok,
locations='Country',
color=dfkm_standarized['Cluster'],
color_discrete_sequence=[high_c, neutral_c, low_c],
mapbox_style='open-street-map', #there are more in mapbox
zoom=0.35,
center={'lat': 30, 'lon': 0},
opacity=0.85,
title='K-means Clustering',
labels={'Ladder score':'Happines Index'},
height=400, #width=800
)
fig.update_layout(margin={"r":0,"t":15,"l":15,"b":15},
paper_bgcolor='#f2f2f2',
title_font_family='Arial',
title_font_color='#323232',
title_font_size=20,
title_x=0.025,
title_y=0.94
)
# Display figure
fig.show()
In general, the index's behavior follows regional dynamics; we find 'happy continents' and 'sad continents.' Europa and North America are the happiest regions, whereas Africa and Asia's south have the lowest happiness levels. The majority of Latin American and Caribbean countries are located above the global median.
Since 2007, the bottom half of the table has been dominated by African countries, while the top half has been dominated by European countries, implying that the index is following a trend. Since 2005, just 11 different countries have ranked in the top three, implying a concentration at the top of the rankings.
Of the indices' associated metrics, per capita income, life expectancy, and social support are the most important in determining happiness. The happiest countries are those with higher levels of income, higher life expectations, and strong social support.
The global average of the index and its metrics is higher than it was ten years ago, implying that the world is a happier place today. However, when the data is compared to the year 2020, there is a significant lag. It appears that it took about two years for the COVID 19 to have the greatest negative impact on the global population's happiness. This impact was uneven throughout the sample of countries. This impact was uneven across the sample of countries; some countries had big increases in happiness, while others experienced sharp drops, with the latter dragging the global average down.
Colombia
Colombia is ranked 52nd in the world, with this year's figures being among the lowest in recent years. Every metric associated with the index is higher than the global average.
All-inclusive In the last ten years, Colombia, Latin America, and the Caribbean have seen a decline in their levels of happiness. This decline is being caused by a drop in Latin America, while in the Caribbean has increased.
!jt -l
Available Themes: chesterish grade3 gruvboxd gruvboxl monokai oceans16 onedork solarizedd solarizedl
!jt -t gruvoxd