Dos 10 países mais felizes do mundo 9 são Europeus. Entre os 10 menos felizes, 8 são Africanos. E não para por aí..
World Happiness Report 2021 #1 :
Se você acessou esse artigo é porque se impressionou com o dado do título, e eu também!
Confesso que não esperava que um simples case de estudo de Python iria me provocar tantos questionamentos sobre nosso mundo.
Nas linhas que seguem iremos conhecer um pouco sobre o World Happiness Report e como manipular sua base de dados usando Python e suas bibliotecas para tirar insights que nos provoquem e nos estimulem a procurar respostas sobre a felicidade no planeta terra. Vamos nessa?
WHR 2021
O Relatório de Felicidade Mundial é uma pesquisa histórica sobre o estado de felicidade global. O relatório continua a ganhar reconhecimento global à medida que governos, organizações e sociedade civil usam cada vez mais os indicadores de felicidade para informar suas decisões de formulação de políticas. Os principais especialistas em todos os campos — economia, psicologia, análise de pesquisas, estatísticas nacionais, saúde, políticas públicas e muito mais — descrevem como as medições de bem-estar podem ser usadas de forma eficaz para avaliar o progresso das nações. Os relatórios analisam o estado da felicidade no mundo hoje e mostram como a nova ciência da felicidade explica as variações pessoais e nacionais da felicidade
Esse Dataset está disponível no kaggle, nesse link :
Variável dependente:
- Ladder Score (índice de felicidade)
Variáveis explicativas :
- The statistics of GDP per capita
- Healthy Life Expectancy (HLE)
- Social support
- Freedom to make life choices
- Generosity
- Corruption Perception
Importando Bibliotecas:
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
Acabamos de importar as caixas de ferramentas que irão nos auxiliar no processo de leitura, manipulação e visualização dos nossos dados.
Numpy →Essa biblioteca nos auxilia com computação numérica. Seu principal objeto é o vetor n-dimensional, ou ndarray. É com essa biblioteca que poderemos manipular arrays e matrizes.
Matplotlib →Nessa biblitoteca encontra-se recursos para a geração de gráficos 2D a partir de arrays e serve de base para outras bibliotecas de visualização. Se você compreender como ela se estrutura, estará apto para fazer gráficos incríveis com python!
Seaborn →Baseado no Matplotlib. Ele provê uma interface de alto nível para construção de gráficos estatísticos atrativos e informativos
Plotly.express →Essa biblioteca me deu uma paz no coração, pois gera gráficos altamente interativos e customizados, muito potente! Eu não conhecia até esse estudo, daqui em diante sempre conto com ela.
Por último e não menos (mais) importante:
Pandas →Se você está estudando ou já trabalha na área de Data analysis/ Data Science já deve conhecer essa biblioteca que nos ajuda desde a leitura dos dados até analises exploratórias profundas!
Definindo a paleta e o estilo dos nossos gráficos
sns.set_palette("Accent")sns.set_style("darkgrid")
A importância da escolha da paleta e do estilo:
Aqui você deve se preocupar com uma paleta e estilo que faça o gráfico ser facilmente compreendido e consiga passar com eficiência e honestidade sua informação. Listei abaixo uma série de opções, divirta-se!
# palette → Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r, BuGn, BuGn_r, BuPu, BuPu_r, CMRmap, CMRmap_r, Dark2, Dark2_r, GnBu, GnBu_r, Greens, Greens_r, Greys, Greys_r, OrRd, OrRd_r, Oranges, Oranges_r, PRGn, PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r, Pastel2, Pastel2_r, PiYG, PiYG_r, PuBu, PuBuGn, PuBuGn_r, PuBu_r, PuOr, PuOr_r, PuRd, PuRd_r, Purples, Purples_r, RdBu, RdBu_r, RdGy, RdGy_r, RdPu, RdPu_r, RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, Reds, Reds_r, Set1, Set1_r, Set2, Set2_r, Set3, Set3_r, Spectral, Spectral_r, Wistia, Wistia_r, YlGn, YlGnBu, YlGnBu_r, YlGn_r, YlOrBr, YlOrBr_r, YlOrRd, YlOrRd_r, afmhot, afmhot_r, autumn, autumn_r, binary, binary_r, bone, bone_r, brg, brg_r, bwr, bwr_r, cividis, cividis_r, cool, cool_r, coolwarm, coolwarm_r, copper, copper_r, cubehelix, cubehelix_r, flag, flag_r, gist_earth, gist_earth_r, gist_gray, gist_gray_r, gist_heat, gist_heat_r, gist_ncar, gist_ncar_r, gist_rainbow, gist_rainbow_r, gist_stern, gist_stern_r, gist_yarg, gist_yarg_r, gnuplot, gnuplot2, gnuplot2_r, gnuplot_r, gray, gray_r, hot, hot_r, hsv, hsv_r, icefire, icefire_r, inferno, inferno_r, jet, jet_r, magma, magma_r, mako, mako_r, nipy_spectral, nipy_spectral_r, ocean, ocean_r, pink, pink_r, plasma, plasma_r, prism, prism_r, rainbow, rainbow_r, rocket, rocket_r, seismic, seismic_r, spring, spring_r, summer, summer_r, tab10, tab10_r, tab20, tab20_r, tab20b, tab20b_r, tab20c, tab20c_r, terrain, terrain_r, viridis, viridis_r, vlag, vlag_r, winter, winter_r
# style → white, dark, whitegrid, darkgrid, ticks
Leitura dos dados
No nosso Dataset há colunas que não serão úteis para a nossa análise. São colunas de referencias estatísticas que não serão, por hora, utilizadas na nossa análise. Ficaremos, portanto, com as colunas que contém nossas variáveis explicativas.
tabela_2021 = pd.read_csv('world-happiness-report-2021.csv')
tabela_2021 = tabela_2021[['Country name', 'Regional indicator', 'Ladder score',
'Logged GDP per capita', 'Social support', 'Healthy life expectancy',
'Freedom to make life choices', 'Generosity',
'Perceptions of corruption']]
tabela_2021
Agora que já lemos os nossos dados, vamos começar a conhecer nosso Dataset, preparados?
Checando dados faltantes e os tipos dos valores das colunas:
O primeiro passo depois de lê um Dataset é verificar se há dados faltantes ou nulos. Esse passo é fundamental para que tenhamos um dataset limpo e assim possamos extrair as melhores informações possíveis dele.
tabela_2021.info()
Nosso dataset não possui nenhum dado nulo! Importante atentar ao Dtype das colunas. Na maioria dos casos teremos que fazer um processo de Data cleaning para ajustar dados faltantes e tipos de dados que possam dificultar nossa manipulação.
Verificando o tamanho do nosso Dataset:
tabela_2021.shape
O retorno que temos é (149, 9). Isto indica que temos um Dataset com 149 linhas e 9 colunas.
Agora estamos aptos a tirar valor dos nossos dados!
Quantos países e de quais regiões são esses países?
regioes = pd.DataFrame(tabela_2021['Regional indicator'].value_counts())
regioes
Análises Preliminares:
Iremos fazer uma tabela com as principais estatísticas do Dataset, e você vai perceber como Python e suas bibliotecas são potentes, com poucas linhas temos:
describe = tabela_2021.describe().round(2).transpose()
describe
Buscando a relação entre Média e Mediana:
describe[['mean', '50%']]
Observações:
- A média do Ladder score é igual a sua mediana. Forte indicio que temos uma distribuição Normal.
- A média de felicidade é de 5,53, em uma escala que vai até 10.
- 50% dos países tem seu Ladder score até 5,53
Vamos ver graficamente como a distribuição do Ladder Score se assemelha a uma distribuição Normal? Vamos usar a biblioteca Seaborn para isso:
ax1 = sns.distplot(tabela_2021['Ladder score'], norm_hist=True)
ax1.figure.set_size_inches(16, 8)
ax1.set_title('Distribuição de Frequências - Ladder', fontsize=18,)
ax1.set_xlabel('Indice de felicidade', fontsize=14)
ax1=0
Observando o Grágico Boxplot no Seaborn e no Plotly
O Boxplot é um dos gráficos que mais demorei para compreender sua utilidade, e pra mim, hoje, é um dos mais importantes. É nele que conseguimos enxergar outliers, o comportamento da média, da mediana e seus quartis. Para qualquer análise exploratória de dados é vital saber interpretar esse tipo de gráfico.
fig = sns.boxplot(data=tabela_2021['Ladder score'], orient='h')
fig.figure.set_size_inches(14, 6)
fig.set_title('Box plot - Ladder', fontsize=18,)
fig.set_xlabel('Indice de felicidade', fontsize=14)
fig
agora faremos com o Plotly:
fig = px.box(tabela_2021, x='Ladder score', orientation= 'h', title= 'Boxplor do Indice de felicidade')
fig.show()
No pycharm ou em outra IDE vocês poderão passar o cursor do mouse sobre o gráfico feito pelo plotly e ele fornecerá as estatísticas em cima do gráfico, além de ser possível destacar parte específica com um zoom out.
Observações
- Pelo boxplot é possível detectar que há um outlier na amostra, no caso, esse outlier é o Afeganistão com Ladder score de 2,523. Falaremos mais sobre o Afeganistão em um próximo post.
Analisando a correlação entre as variáveis:
Agora vamos plotar um dataframe com o calculo de correlação entre todas as variáveis. Elas se relacionam entre si? Em que grau? São perguntas que o calculo da estatística de correlação vai nos ajudar a responder, embora seja necessário fazer mais testes específicos, essa estatística já nos mostra uma boa pista sobre a relação entre nossas variáveis.
cor =tabela_2021.corr().round(2)
cor
Observações
- Primeiro: Analisar linha 1 do Data Frame, é nela que poderemos observar o índice de correlação da variável dependente(Ladder score) com as variáveis explicativas.
- Segundo: Importante observar a correlação entre as variáveis explicativas para futuras modelagens de regressão e analises mais aprofundadas.
- A variável explicativa “Generosity” aparenta não está correlacionada com o Ladder Score.
- Curioso o fato da percepção da generosidade não está correlacionada com felicidade. Dois sentimentos genuínos aparentemente não estão correlacionados.
- Será que um Dataframe de correlação é a melhor forma de apresentar essa estatística?
Elaborando heatmap para melhor visualizar as estatísticas de correlação
Visualizar a correlação em um gráfico de calor, com uma boa paleta de cores, facilita muito o nosso trabalho de tirar valor dos dados. Compreender os números pelas cores é de mais rápida compreensão. Então, sugiro que você use e abuse da didática das cores e de gráficos mais interativos para apresentar seus insights para seu chefe, sua equipe e demais colegas de estudo ou trabalho.
E olha como é simples montar uma representação gráfica da correlação:
plt.figure(figsize=(20,8))
sub = np.triu(tabela_2021.corr())
sns.heatmap(cor, annot=True, linewidths=0.2, cmap='coolwarm', square=True, mask=sub)
Melhor, né? :)
Matriz de correlação:
O coeficiente de correlação é uma medida de associação linear entre duas variáveis e situa-se entre -1 e +1 sendo que -1 indica associação negativa perfeita e +1 indica associação positiva perfeita.
Agora vamos focar especificamente na relação das variáveis explicativas com a nossa variável dependente. Daquele mesmo Dataframe que calculamos a correlação, selecionarei apenas a coluna da nossa variável dependente:
cor['Ladder score']Ladder score 1.00
Logged GDP per capita 0.79
Social support 0.76
Healthy life expectancy 0.77
Freedom to make life choices 0.61
Generosity -0.02
Perceptions of corruption -0.42
Name: Ladder score, dtype: float64
Observações
- Todas as variáveis, com exceção de Generosity, está bem correlacionada com o índice de felicidade
- As 3 variáveis com maior correlação direta são: PIB per capita, Social support, Healthy life expectancy
- Perceptions of corruption apresenta uma correlação inversa de -0,42, em uma escala que vai de ‘-1 a 1’
Outras formas de enxergar a correlação: Gráfico de dispersão!
Nosso objetivo agora é plotar um gráfico de dispersão entre a variável dependente ( Ladder Score) e as independentes, uma por vez.
Para tal, usamos a biblioteca Seaborn que nos trouxe um resultado visual incrível. Além de trazer a dispersão, também nos mostra a curva de densidade de cada variável. Vamos testar?
Ah! Para não termos que copiar e colar varias vezes o mesmo código, resolvi fazer um laço/loop para deixar nosso trabalho mais fácil.
for coluna in tabela_2021[['Logged GDP per capita', 'Social support', 'Healthy life expectancy',
'Freedom to make life choices', 'Generosity',
'Perceptions of corruption']]:
plot = sns.jointplot(x = coluna,
y = 'Ladder score',
data = tabela_2021,
hue = 'Regional indicator',
height= 10)plot
Observações
- No gráfico, cada pontinho representa um país e sua cor representa sua região. Já conseguimos ter uma boa noção das regiões mais felizes e das menos felizes, né?
- Nos gráficos de dispersão acima é possível observar como há evidente correlação positiva entre o Ladder Score e PIB per capita, Social support, Healthy life expectancy e Freedom to make life choices
- Na variável Generosity percebe-se que não há correlação, é necessário fazer outros testes para se aferir melhor a relação desta variável explicativa com o Índice de felicidade.
- A variável de Perceptions of corruption apresenta uma correlação inversa com o índice de felicidade. Assume uma tendência de quanto menor a percepção de corrupção, maior o índice de felicidade.
Finalizamos nossa primeira análise geral sobre as principais estatísticas das variáveis e como elas se relacionam, agora respira! O próximo passo vai ser estudar como se comporta o índice de Felicidade entre as regiões.
Como o Ladder score se comporta por região?
Para analisar o Ladder score por região o caminho mais eficiente é agruparmos os países de acordo com sua região. O método groupby nos permitirá observar estatísticas agregadas do países agrupados.
## Agrupando as regiões para conhecer as métricas estatísticastabela_regioes = tabela_2021.groupby('Regional indicator')
tabela_regioes<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f1c559d3160>
Uma vez agrupados, poderemos então chamar um quadro geral de estatísticas. Para ficar melhor o entendimento, ordenarei a tabela pelo índice de felicidade.
df_media = tabela_regioes.mean().sort_values('Ladder score')
df_media
O South Asia apresenta a menor média do Índice de Felicidade, entretanto devemos nos atentar. Temos que levantar a hipotese de que o outlier do nosso conjunto de dados, o Afeganistão, pode tá desbalanceando a média dessa região. Vamos plotar um gráfico para visualizar melhor as médias de cada região?
fig = px.bar(df_media, x= 'Ladder score', y= df_media.index, orientation='h',
labels={'Ladder score':'Indice de felicidade'},
height=500, color_continuous_scale= 'deep')
fig.show()
Para enriquecer nossa análise, poderíamos plotar um gráfico que houvesse um degradê de cores que indicasse como as variáveis independentes se comportam em cada região. Dessa forma, incluiremos mais uma dimensão no nosso gráfico. Irei criar um laço/loop para plotarmos nosso gráfico anterior, desta vez dialogando com as 6 variáveis independentes.
for coluna in tabela_2021[['Logged GDP per capita', 'Social support', 'Healthy life expectancy',
'Freedom to make life choices', 'Generosity',
'Perceptions of corruption']]:fig = px.bar(df_media, x= 'Ladder score', y= df_media.index, orientation='h',
labels={'Ladder score':'Indice de felicidade'},
height=400, color = coluna, color_continuous_scale= 'deep')
fig.show()
Analisando os 20 mais e menos felizes do mundo:
Arbitrariamente decidimos analisar o Top 20 dos mais e menos felizes, dessa forma teremos um grupo de países mais amplos para estudarmos as estatísticas agregadas desse grupo. Criei um Dataframe ordenado pelo Ladder score e separei os mais_felizes e os menos_felizes
## Selecionando os 20 mais felizes e menos felizesladder_score = tabela_2021.sort_values("Ladder score",ascending=False)
Uma vez ordenados pelo índice de felicidade, dividimos os grupos:
mais_felizes =ladder_score.head(20)
mais_felizes
menos_felizes =ladder_score.tail(20)
menos_felizes.sort_values("Ladder score",ascending=True)
Agora iremos plotar as principais estatísticas sobre esses dois grupos:
mais_felizes.describe().round(2)
menos_felizes.describe().round(2)
Distribuição do Ladder Score nas duas seleções
Iremos agora analisar a distribuição de frequencia do índice de felicidade nos dois conjuntos. Vimos anteriormente que a distribuição de frequência do conjunto inteiro segue uma curva normal. Será que nos dois conjuntos teremos a mesma representação de curva?
ax1 = sns.distplot(mais_felizes['Ladder score'], norm_hist=True)
ax1.figure.set_size_inches(14, 6)
ax1.set_title('Distribuição de Frequências - Ladder', fontsize=18,)
ax1.set_xlabel('Indice de felicidade', fontsize=14)
ax1=0
ax1 = sns.distplot(menos_felizes['Ladder score'], norm_hist=True)
ax1.figure.set_size_inches(14, 6)
ax1.set_title('Distribuição de Frequências - Ladder', fontsize=18,)
ax1.set_xlabel('Indice de felicidade', fontsize=14)ax1=0
Observando os dois conjuntos com Boxplot:
fig = px.box(mais_felizes, x='Ladder score', orientation= 'h', title= 'Boxplor do Indice de felicidade')
fig.show()
fig = px.box(menos_felizes, x='Ladder score', orientation= 'h', title= 'Boxplor do Indice de felicidade')
fig.show()
Observações:
Há assimetrias nos dois conjuntos. Entre os mais_felizes a média se comporta ainda em um valor acima de 7,00. Entre os menos_felizes há um evidente outlier que pontua abaixo de 2,6 no Ladder score. Esse outlier é o Afeganistão.
Mesmo entre os 20 menos_felizes, esse país ainda destoa do índice de felicidade médio desses países. Com certeza é um assunto para nos aprofundar em um próximo post
Como as regiões são representadas entre os mais_felizes e os menos_felizes?
Iremos usar o mesmo método value_counts, desta vez nos trazendo o valor em porcentagem.
mais_felizes['Regional indicator'].value_counts(normalize=True*100)Western Europe 0.65
North America and ANZ 0.20
Middle East and North Africa 0.05
Latin America and Caribbean 0.05
Central and Eastern Europe 0.05
Name: Regional indicator, dtype: float64
Agora dos menos_felizes :
menos_felizes['Regional indicator'].value_counts(normalize=True*100)Sub-Saharan Africa 0.75
South Asia 0.10
Middle East and North Africa 0.10
Latin America and Caribbean 0.05
Name: Regional indicator, dtype: float64
A frieza dos números não conseguem esconder que entre os mais_felizes 70% estão na Europa e que dos menos_felizes 80% estão na África.
Extraindo os 10 mais felizes e os 10 menos felizes:
mais_felizes.head(10)
menos_felizes.head(10)
Olhando o conjunto dos 10 mais e menos felizes, chegamos a uma conclusão que nos faz pensar sobre como o planeta terra ainda é muito desigual.
Entre os 10 mais felizes, 9 estão na Europa e entre os 10 menos felizes, 8 estão na África.
Colonizadores e colonizados, o mundo ainda sente o peso daquele período histórico que devastou povos originários, suas culturas e suas riquezas.
O Ladder Score e suas variáveis explicativas explicitam que na escada que fazem as civilizações alcançarem a felicidade há uma evidente assimetria de condições econômicas, sociais, de liberdade e de expectativas que separam, ainda hoje, os colonos dos colonizados. Até quando? Dignidade e felicidade para todos.
Nos próximos posts dessa sequência sobre o World Happiness Report 2021 ainda falaremos sobre o nosso outlier Afeganistão, da relação de felicidade entre Brasil e Portugal na série histórica, e sobre o impacto das variáveis explicativas na construção do Índice de felicidade, através de um modelo de regressão linear. Até lá!