## Europe Happiness¶

In this notebook we visualize Europe countries happiness scores. Data are retrieved from World Happiness Report 2016.

In [1]:
import numpy as np
import pandas as pd
import matplotlib.cm as cm

In [2]:
df = pd.read_excel('Data/Europe-Happiness.xlsx')
df.head()

Out[2]:
Country World-Rank Score
0 Denmark 1 7.526
1 Switzerland 2 7.509
2 Iceland 3 7.501
3 Norway 4 7.498
4 Finland 5 7.413
In [3]:
N = len(df)

In [4]:
score = df['Score'].values
country = list(df.Country)
country[13] = 'U Kingdom'
country[14] = 'Czech Rep'
country[38] = 'Bosn Herzeg'
world_rk = list(df['World-Rank'])

In [5]:
import plotly.plotly as py
import plotly.graph_objs as go


Function that maps a normalized happiness score to a color in a given matplotlib colormap:

In [6]:
def map_z2color(val, colormap, vmin, vmax):
#map the normalized value val to a corresponding color in the mpl colormap

if vmin >= vmax:
raise ValueError('incorrect relation between vmin and vmax')
t = (val-vmin) / (vmax-vmin) #normalize val
C = (np.array(colormap(t)[:3])*255).astype(np.uint8)
#convert to a Plotly color code:
return f'rgb{tuple(C)}'

In [7]:
def set_layout(title, plot_size):# set plot layout

return go.Layout(title=title,
font=dict(size=12),
xaxis=dict(visible=False, range=[-3.5, 4]),
yaxis=dict(visible=False, range=[-4.5, 3.5]),
showlegend=False,
width=plot_size,
height=plot_size,
hovermode='closest')

In [8]:
def set_annotation(x, y, anno_text,  angle, fontsize=11): # annotations
return dict(x= x,
y= y,
text= anno_text,
textangle=angle, # angle in degrees
font=dict(size=fontsize),
showarrow=False
)


We visualize countries happiness through a circular barchart. The height of each bar is proportional to the corresponding happiness score:

In [9]:
bar_height = [score[k]/4.75 for k in range(N)]


The bars are inserted along the unit circle, starting with the angular position $\pi/2$, in the anti-clockwise direction:

In [10]:
theta = [np.pi/2+(2*k+1)*np.pi/72  for k in range(N)] # angular position of base bar centers

In [11]:
xi = [np.cos(theta[k]) for k in range(N)]# starting bar position
yi = [np.sin(theta[k]) for k in range(N)]

xf = [(bar_height[k]+1)*np.cos(theta[k]) for k in range(N)]#end bar position
yf = [(bar_height[k]+1)*np.sin(theta[k]) for k in range(N)]

xm = [(xi[k]+xf[k])*0.5   for k in range(N)]#mid bar position for inserting hovering text
ym = [(yi[k]+yf[k])*0.5   for k in range(N)]

xpos_t = [(bar_height[k]+1.32)*np.cos(theta[k]) for k in range(N)]#text position
ypos_t = [(bar_height[k]+1.32)*np.sin(theta[k]) for k in range(N)]


The decreased level of happiness is illustrated through the Viridis colormap:

In [12]:
import matplotlib.cm as cm
cmap = cm.viridis

In [13]:
vmin = score[-1]
vmax = score[0]
bar_colors = [map_z2color(score[k], cmap, score[-1], score[0]) for k in range(N)]


Define the hover text:

In [14]:
text = [f'{country[k]}<br>Score: {round(score[k],3)}<br>World rank: {world_rk[k]}'  for  k in range(len(score))]


Set position of the hover text inside bars:

In [15]:
trace = go.Scatter(x=xm,
y=ym,
name='',
mode='markers' ,
marker=dict(size=0.05, color=bar_colors[15]),
text=text,
hoverinfo='text')
tracet = go.Scatter(x=xf,
y=yf,
name='',
mode='markers' ,
marker=dict(size=0.05, color=bar_colors[15]),
text=text,
hoverinfo='text')

In [16]:
traceB = [go.Scatter(x=[xi[k], xf[k], None], # Circular bars are drawn as lines of width 9
y=[yi[k], yf[k], None],
mode='lines',
line=dict(color=bar_colors[k], width=9.6),
hoverinfo='none')  for k in range(N)]

In [17]:
title = "Europe Happiness Score and Global Ranking"+\
"<br>Data: World Happiness Report, 2016"+\
"<a href='http://worldhappiness.report/wp-content/uploads/sites/2/2016/03/HR-V1_web.pdf'> [1]</a>"
layout = set_layout('', 900)

In [18]:
annotext_angle = [(-(180*np.arctan(yi[k]/xi[k])/np.pi)) for k in range(N)]# angles in degrees, computed following
#Plotly reversed trigonometric rule


Define and insert annotations in plot layout:

In [19]:
annot = []
for k in range(N):
annot += [set_annotation(xpos_t[k], ypos_t[k], country[k],  annotext_angle[k],  fontsize=10)]
annot += [set_annotation(0.5, 0.1, title, 0 ) ]

In [20]:
fig = go.FigureWidget(data=traceB+[trace, tracet], layout=layout)

In [21]:
fig.layout.update(annotations=annot,
plot_bgcolor='rgb(245,245,245)');
fig

In [ ]: