Open In Colab

1. Introdução


A visualização de dados é antes de tudo uma forma de transmitir ou comunicar os dados com precisão e existem ao menos dois tipos de visualização de dados com requisitos bastante diferentes. O primeiro é voltado para a análise e envolve a Exploração dos Dados como a descoberta padrões, relações e processos em ação sobre os dados. Neste tipo de visualização você experimenta diferentes tipos de gráficos e visualizações, de transformações e seleções dos dados. Aspectos estéticos das figuras produzidas tem aqui uma importância secundária.

O segundo tipo de visualização tem por objetivo a Apresentação de Resultados e busca fornecer informações claras e visualmente atraentes para uma apresentação ou a sua publicação. Aqui, a qualidade das figuras produzidas é mais essencial e devem ser atraentes e comunicar de forma eficiente os dados para um determinado público.

Ambos os tipos de visualização podem ser feitos com Python, assim como em outras linguagens e ferramentas. Como um texto introdutório os recursos que estudaremos neste livro serão mais voltados para análise e exploração de dados, mas podem ser igualmente empregados na produção de visualizações finais de dados.

\(\bigstar \text{ }\) Existem ao menos dois tipos de visualização de dados com requisitos bastante diferentes, e podemos dizer que existem Gráficos de Exploração e Gráficos de Apresentação.

1.1. Importância da Visualização de Dados

O Quarteto de Anscombe (F.J. Anscombe, 1973) é um exemplo conhecido que ilustra o valor da visualização para o entendimento dos dados mesmo quando várias informações, como variáveis estatísticas, podem ser obtidas. Ele é formado por quatro conjuntos de dados que aparentam idênticos por técnicas da estatística descritiva como a média e a variância, mas que são muito distintos quando exibidos graficamente.

Os quatro conjuntos apresentam, com até 3 casas decimais, as mesmas médias e variâncias tendo todos o mesmo modelo de regressão linear:

\[ y = 3 + 0.5 x\]
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
%matplotlib inline
# Load Anscombe's quartet
df = sns.load_dataset("anscombe")

# Mostra os resultados de um modelo de regressão linear
sns.lmplot(x="x", y="y", col="dataset", hue="dataset", data=df,
           col_wrap=2, ci=None, palette="muted", height=4,
           scatter_kws={"s": 50, "alpha": 1})
plt.suptitle('Anscombe Quartet', fontsize=14, weight='bold', y=1.05)
plt.show()
_images/c0_intro_6_0.png

Não se preocupe com o código agora, você vai aprender mais sobre ele adiante. Aqui o importante é você entender que um exemplo bastante simples de dados já demonstra padrões e relações que podem ser difíceis de serem observadas sem o auxílio de uma visualização dos dados.

Exemplos mais elaborados podem ser facilmente obtidos como você pode ver a seguir.

import pandas as pd
cars = pd.read_csv('https://raw.githubusercontent.com/Rogerio-mack/Visualizacao-de-Dados-em-Python/main/data/mtcars.csv')
cars.head()
model mpg cyl disp hp drat wt qsec vs am gear carb
0 Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
1 Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
2 Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
3 Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
4 Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
sns.clustermap(cars.set_index('model'), metric='euclidean', standard_scale=1, method='ward', figsize=(8,8.5))
plt.title('Heatmap Cars', fontsize=14, weight='bold')
plt.show()
_images/c0_intro_9_0.png

A visualização acima é um Mapa de Calor (Heat Map) e ele representa por cores valores de cada atributo dos veículos. Ele permite observarmos padrões e relações sobre os dados que dificilmente poderíamos observar de outro modo. Podemos, por exemplo, identificar grupos de veículos com características comuns e, mesmo um leigo, pode facilmente compreender essas informações.

A visualização de dados pode contribuir para a compreensão de dados bastante complexos e distantes dso dados numéricos e estruturados em tabelas que talvez você esteja habituado. Gráficos como uma WordCloud (abaixo) permitem analisar o conteúdo uma coleção de documentos a partir das palavras mais frenquentes que apresentam. Isso tem uma série de aplicações práticas como identificar as principais reclamações de clientes em um conjunto de e-mails ou os temas mais comentados no Twitter.

# World Cloud a partir do texto de prefácio deste livro
import urllib.request  
from wordcloud import WordCloud, STOPWORDS
import nltk
from nltk.corpus import stopwords
nltk.download('stopwords')

texto = []
for line in urllib.request.urlopen('https://raw.githubusercontent.com/Rogerio-mack/Visualizacao-de-Dados-em-Python/main/intro.ipynb'): 
    texto.append(line.decode('utf-8'))

stopwords = set( stopwords.words('portuguese'))

texto_string = ''
for line in texto: 
  texto_string = texto_string + ' ' + line.lower()  

wordcloud = WordCloud(width = 600, height = 600,
				background_color ='lightgrey',
				stopwords = stopwords,
				min_font_size = 10).generate(texto_string)

print('\n')
plt.figure(figsize = (7, 7), facecolor = None)
plt.suptitle('Uma WordCloud do Prefácio deste Livro', fontsize=14, weight='bold', y=1.05)
plt.imshow(wordcloud)
plt.axis("off")
plt.tight_layout(pad = 0)

plt.show()
[nltk_data] Downloading package stopwords to
[nltk_data]     C:\Users\User\AppData\Roaming\nltk_data...
[nltk_data]   Package stopwords is already up-to-date!

_images/c0_intro_11_2.png

Esses poucos exemplos já dá ideia do papel importante da visualização para a compreensão e a análise de grandes conjuntos de dados e, ao longo deste texto, você encontrará uma série de análises como essas.

1.2. Fazendo Perguntas Relevantes sobre os Dados

Compreender e analisar dados é basicamente buscar respostas para hipóteses que fazemos sobre os dados. Que tipo de perguntas podemos fazer sobre os dados e a visualização pode nos ajudar a responder?

Podemos agrupar as perguntas que fazemos sobre os dados em algumas categorias. Por exemplo, se estamos interessados em como a temperatura evolui ao longo do dia, nossa pergunta parece ser sobre a evolução dessa variável e um gráfico de linhas parece ser o mais adequado para essa análise. Para cada uma das categorias há gráficos que, em geral, são mais indicados:

Evolução (ou Tendência dos Dados): gráficos de linha e de área, séries múltiplas

Distribuição: histogramas, gráficos densidade de probabilidade, gráficos de caixa

Quantidades e Proporções: gráficos de barras e pizza, mapas de árvore

Relações: gráficos de dispersão, correlogramas e mapas de calor

e podemos pensar em outras categorias e muitos outros tipos de gráficos. Mas por hora essas categorias são suficientes e veremos várias alternativas de gráficos para cada uma dessas classes de perguntas. Boa parte deste livro se dedica a entender exatamente que gráficos empregar para obtermos respostas dos dados em cada caso.

Vamos ver mais alguns exemplos. Você pode explorar os códigos aqui se quiser, mas não precisa se preocupar com eles agora. Eles estão aqui apenas para produzir as figuras os códigos serão discutidos mais adiante no texto.

1.3. Evolução

Muitas vezes estamos interessados na evolução dos valores de uma variável com relação ao tempo ou alguma outra variável. Queremos saber sobre a tendência dessa evolução, sobre a probabilidade de se alcançar um certo valor ou ainda queremos comparar a evolução de duas variáveis que esperamos tenham alguma relação.

Quando essas variáveis são numéricas um gráfico de linhas é frequentemente usado para visualizar a tendência dos dados e responder a essas perguntas. Quanto uma dessas variáveis representa o tempo denominamos o conjunto de dados como séries temporais.

A visualização permite entendermos como uma variável evolui com relação a outra. Por exemplo, você pode identificar tendências de longo prazo e flutuações da moeda americana exibindo sua evolução a partir de um gráfico de linhas.

# Obtendo os dados
bovespa = pd.read_csv('https://raw.githubusercontent.com/Rogerio-mack/Visualizacao-de-Dados-em-Python/main/data/mystocksn.csv')
bovespa.data = pd.to_datetime(bovespa.data, format='%Y-%m-%d',errors='coerce') 
bovespa.head()
data IBOV VALE3 PETR4 DOLAR
0 2020-02-27 102984.0 9.92 12.08 4.4491
1 2020-02-28 104172.0 9.82 12.10 4.4848
2 2020-03-02 106625.0 10.27 12.49 4.4413
3 2020-03-03 105537.0 10.22 12.16 4.4724
4 2020-03-04 107224.0 10.56 12.33 4.5132
# Construindo o gráfico
import matplotlib.ticker as ticker
import numpy as np
fig, ax = plt.subplots(figsize=(12,4))

ax.plot(bovespa.data, bovespa.DOLAR, label='DOLAR')

z = np.polyfit(bovespa.index,bovespa.DOLAR, 1)
p = np.poly1d(z)
ax.plot(bovespa.data,p(bovespa.index), linestyle='dashed', label='Linear(x)' ,linewidth=2, color='k')

ax.set_title('Tendência do Dólar', fontsize=14, weight='bold')
ax.set_xlabel("date")
ax.set_ylabel("Valor (R$)")
ax.legend(fontsize=12)
ax.xaxis.set_major_locator(ticker.MaxNLocator(8))

plt.show()
_images/c0_intro_16_0.png

1.4. Distribuição

Os dados a seguir são da Organização Mundial e Saúde (WHO World Health Organization) e incluem diversos indicadores de saúde e de desenvolvimento dos países. Uma pergunta relevante que você poderia fazer sobre os dados é sobre como são distribuídos os valores de Produto Interno Bruto dos países ou ainda a Expectativa de Vida média dos indivíduos entre países Desenvolvidos e em Desenvolvimento.

# Obtendo os dados
WHO = pd.read_csv('https://raw.githubusercontent.com/Rogerio-mack/Visualizacao-de-Dados-em-Python/main/data/Life_Expectancy_Data.csv')
WHO.rename(columns={' BMI ':'BMI', 'Life expectancy ':'Life_expectancy'}, inplace=True)
WHO = WHO[ WHO.Year == 2015 ]
WHO.head()
Country Year Status Life_expectancy Adult Mortality infant deaths Alcohol percentage expenditure Hepatitis B Measles ... Polio Total expenditure Diphtheria HIV/AIDS GDP Population thinness 1-19 years thinness 5-9 years Income composition of resources Schooling
0 Afghanistan 2015 Developing 65.0 263.0 62 0.01 71.279624 65.0 1154 ... 6.0 8.16 65.0 0.1 584.259210 33736494.0 17.2 17.3 0.479 10.1
16 Albania 2015 Developing 77.8 74.0 0 4.60 364.975229 99.0 0 ... 99.0 6.00 99.0 0.1 3954.227830 28873.0 1.2 1.3 0.762 14.2
32 Algeria 2015 Developing 75.6 19.0 21 NaN 0.000000 95.0 63 ... 95.0 NaN 95.0 0.1 4132.762920 39871528.0 6.0 5.8 0.743 14.4
48 Angola 2015 Developing 52.4 335.0 66 NaN 0.000000 64.0 118 ... 7.0 NaN 64.0 1.9 3695.793748 2785935.0 8.3 8.2 0.531 11.4
64 Antigua and Barbuda 2015 Developing 76.4 13.0 0 NaN 0.000000 99.0 0 ... 86.0 NaN 99.0 0.2 13566.954100 NaN 3.3 3.3 0.784 13.9

5 rows × 22 columns

# Construindo o gráfico
fig, axs = plt.subplots(1, 2, figsize=(12, 4))

sns.histplot(data=WHO, x='GDP', kde=True, color="red", ax=axs[0])
axs[0].set_title('GDP (2015)', fontsize=14, weight='bold') 

sns.histplot(x='Life_expectancy', data=WHO, hue='Status', kde=True, ax=axs[1], bins=25)
axs[1].set_title('Expectativa de Vida (2015)', fontsize=14, weight='bold') 

plt.tight_layout()
plt.show()
_images/c0_intro_19_0.png

Como você pode ver, dados de PIB e Expectativa de via apresentam distribuições bastante diferentes e se você conhece um pouco sobre técnicas de estatística, sabe que identificar a forma dessas distribuições é bastante importante para solução de problemas de inferência estatística e para o entendimento dos dados.

1.5. Quantidades e Proporções

Muitas vezes não estamos interessados na evolução ou distribuição dos dados, mas queremos acessar os valores diretamente em suas unidades, exibindo os valores ou suas proporções para diferentes classes e comparar diferentes conjuntos de dados.

Para isso os gráficos de barras têm várias variantes e são normalmente empregados. Eles permitem exibir as quantidades de uma ou mais variáveis separadas por diferentes categorias ou classes.

# Obtendo os dados
cars = sns.load_dataset('mpg')
cars.head()
mpg cylinders displacement horsepower weight acceleration model_year origin name
0 18.0 8 307.0 130.0 3504 12.0 70 usa chevrolet chevelle malibu
1 15.0 8 350.0 165.0 3693 11.5 70 usa buick skylark 320
2 18.0 8 318.0 150.0 3436 11.0 70 usa plymouth satellite
3 16.0 8 304.0 150.0 3433 12.0 70 usa amc rebel sst
4 17.0 8 302.0 140.0 3449 10.5 70 usa ford torino
# Construindo o gráfico
from matplotlib import cm
fig = plt.figure(figsize=(12,4))

sns.barplot(x='model_year', y='weight', data=cars, hue='origin', alpha=0.7)

plt.title('Peso Médio dos Veículos',fontsize=14,weight='bold')
plt.xlabel('Year Model')
plt.ylabel('Weight')

plt.show()
_images/c0_intro_23_0.png

O gráfico acima, por exemplo, permite observar o peso médio dos veículos produzidos nos USA, Japão e Europa ao longo dos anos e a linha sobre as barras indica o intervalo de confiança (95%) dos dados.

1.6. Relações

Por último, você pode querer analisar relações entre os dados. Essas relações são muitas vezes denominadas de modo bastante geral como correlações. Na estatística, entretanto, a correlação refere-se unicamente a uma relação linear entre os dados. Assim, preferimos empregar aqui o termo relações. Embora relações lineares (correlações) sejam as relações mais comuns que buscamos nos dados, a visualização permite encontrarmos muitos outros padrões além do padrão linear.

Os dados abaixo são uma organização para o desenvolvimento sustentável global (Gapminder). Eles permitem apresentar as relações entre renda, expectativa de vida e o índice de percepção de corrupção (CPI Corruption Perceptions Index) de diferentes países e até mesmo traçar uma linha de tendência.

# Obtendo os dados
gap = pd.read_csv('https://raw.githubusercontent.com/Rogerio-mack/Visualizacao-de-Dados-em-Python/main/data/gapminder_2015.csv')
gap.head()
continent country year demox_eiu income_per_person invest_%_gdp tax_%_gdp gini_index LifeExpect HappyIdx SchoolYears15_24 VacineBelieve ChildMortality Co2Emissions CPI Population
0 Africa Botswana 2015 78.7 15700 32.1 24.7 60.5 66.9 0.376 8.40 NaN 40.7 2.560 63.0 2120000
1 Africa Burkina Faso 2015 47.0 1600 24.3 15.1 35.5 60.7 0.442 3.76 NaN 86.8 0.182 38.0 18100000
2 Africa Cote d'Ivoire 2015 33.1 3230 20.1 15.4 41.6 61.0 0.445 6.59 NaN 90.0 0.405 32.0 23200000
3 Africa Egypt 2015 31.8 10200 14.3 12.5 31.2 70.2 0.476 10.60 NaN 23.6 2.370 36.0 92400000
4 Africa Kenya 2015 53.3 2800 21.5 16.3 41.5 64.7 0.436 9.06 NaN 46.3 0.341 25.0 47900000
# Construindo o gráfico
plt.figure(figsize=(12, 4))

plt.scatter(gap['income_per_person'],gap['LifeExpect'], alpha=0.6, s=120, c=gap['CPI'], cmap=cm.gnuplot2_r)

plt.title('Income $\\times$ Life Expectancy', fontsize=14, weight='bold')
plt.xlabel('Anual Income per Person')
plt.ylabel('Life Expectancy (Years)')

cbar = plt.colorbar()
cbar.set_label('CPI', fontsize=12, weight='bold')

# Produzindo o ajuste da curva
from scipy.optimize import curve_fit

def func(x, a, b):
    return a*np.log(x) + b

coefs, covar = curve_fit(func, gap['income_per_person'], gap['LifeExpect'])

x = np.linspace(gap['income_per_person'].min(), gap['income_per_person'].max(), 100)
y = func(x,*coefs)

plt.plot(x,y,color='black', linestyle='dashed', lw=1.5)

plt.tight_layout()
plt.show()
_images/c0_intro_27_0.png


Cada uma dessas categorias de análise que você viu aqui serão tratadas em detalhe havendo um capítulo para cada uma delas.

O domínio de linguagens e ferramentas como o Python para produzir visualizações são um aspecto importante para que você obtenha resultados corretos na Visualização de Dados. Mas tão importante quanto esse domínio técnico da produção de visualizações dos dados é ter um pensamento analítico sobre os dados compreendendo que perguntas você está buscando responder sobre eles. Sem isso, produzir visualizações dos dados não seria nada além de um exercício gráfico e qualquer caminho parece ser bom quando não se tem ideia onde se quer chegar.