#!/usr/bin/env python # coding: utf-8 # ## Europe Happiness ## # In this notebook we visualize Europe countries happiness scores. Data are retrieved from [World Happiness Report 2016](http://worldhappiness.report/wp-content/uploads/sites/2/2016/03/HR-V1_web.pdf). # # 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() # 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]}
Score: {round(score[k],3)}
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"+\ "
Data: World Happiness Report, 2016"+\ " [1]" 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[ ]: