#!/usr/bin/env python # coding: utf-8 # # Introdução, Tipos de dados e Variáveis Visuais # #
Altair é uma bilioteca de visualizações estatísticas declarativas para Python. # Desse jeito Altair foca no que fazer e não como fazer. A ideia principal da biblioteca é que o designer da visualização especifique a relação dos dados e deixar todas as outras decisões automáticas.
# #A biblioteca é baseada no Vega-Lite, uma gramática poderosa e concisa para construir visualizações rapidamente, e gera gramáticas para renderização em ambientes como Jupyter Notebooks, Jupyter Lab e Colab. De modo geral, vamos utilizar o Altair para facilitar a análise exploratória de dados com uma gramática concisa porém expressiva que especifique gráficos interativos com múltiplas visões.
# Sinta-se a vontade para modificar os exemplos, esse é um documento vivo! # Para começar, vamos importar as bibliotecas. # In[1]: import altair as alt import pandas as pd # ## Dados # # Os dados em Altair são baseados no formato _DataFrame_ do `Pandas`, que é simplesmente um conjunto de dados separados por colunas. Essas colunas podem ser chamadas dimensões, campos ou atributos. # # A utilização de um dataset é muito simples simples, aceitando um _DataFrame_ carregado localmente ou um formato de dados na web através de uma URL. # In[2]: dados = pd.read_csv("https://raw.githubusercontent.com/tiagodavi70/vl-altair-tutorial/master/datasets/dados.csv") dados.head() # Também é possível criar dataframes de uma lista de dicionários. Na lista abaixo temos a listagem de todos os estados da federação com suas regiões e populações estimadas em julho de 2019. Vamos usar esse conjunto e o arquivo `dados.csv` para exemplificar os conceitos do Altair nesse notebook. # In[3]: estados = [ {'estado': 'São Paulo', 'população': 45919049, "região": "Sudeste"}, {'estado': 'Minas Gerais', 'população': 21168791, "região": "Sudeste"}, {'estado': 'Rio de Janeiro', 'população': 17264943, "região": "Sudeste"}, {'estado': 'Bahia', 'população': 14873064, "região": "Nordeste"}, {'estado': 'Paraná', 'população': 11433957, "região": "Sul"}, {'estado': 'Rio Grande do Sul', 'população': 11377239, "região": "Sul"}, {'estado': 'Pernambuco', 'população': 9557071, "região": "Nordeste"}, {'estado': 'Ceará', 'população': 9132078, "região": "Nordeste"}, {'estado': 'Pará', 'população': 8602865, "região": "Norte"}, {'estado': 'Santa Catarina', 'população': 7164788, "região": "Sul"}, {'estado': 'Maranhão', 'população': 7075181, "região": "Nordeste"}, {'estado': 'Goiás', 'população': 7018354, "região": "Centro-Oeste"}, {'estado': 'Amazonas', 'população': 4144597, "região": "Norte"}, {'estado': 'Espírito Santo', 'população': 4018650, "região": "Sudeste"}, {'estado': 'Paraíba', 'população': 4018127, "região": "Nordeste"}, {'estado': 'Rio Grande do Norte', 'população': 3506853, "região": "Nordeste"}, {'estado': 'Mato Grosso', 'população': 3484466, "região": "Centro-Oeste"}, {'estado': 'Alagoas', 'população': 3337357, "região": "Nordeste"}, {'estado': 'Piauí', 'população': 3273227, "região": "Nordeste"}, {'estado': 'Distrito Federal', 'população': 3015268,"região": "Centro-Oeste"}, {'estado': 'Mato Grosso do Sul', 'população': 2778986, "região": "Centro-Oeste"}, {'estado': 'Sergipe', 'população': 2298696, "região": "Nordeste"}, {'estado': 'Rondônia', 'população': 1777225, "região": "Norte"}, {'estado': 'Tocantins', 'população': 1572866, "região": "Norte"}, {'estado': 'Acre', 'população': 881935, "região": "Norte"}, {'estado': 'Amapá', 'população': 845731, "região": "Norte"}, {'estado': 'Roraima', 'população': 605761, "região": "Norte"} ] # In[4]: df = pd.DataFrame(estados) df.shape # 3 colunas e 27 linhas, com isso vamos criar nosso primeiro gráfico. # ## O primeiro gráfico # # O objeto fundamental em Altair é o `Chart`, que aceita um dataframe ou URL como argumento: # In[5]: chart = alt.Chart(df) # Essa é estrutura basica para começar a mapear as váriaveis visuais com os dados. # Com o objeto do gráfico em mãos, agora podemos definir o __que__ queremos visualizar, começando com a definição da marca visual que nós queremos associar aos dados. Em Altair isso é possível usando o atributo `mark` do objeto usando métodos do tipo `Chart.mark_*`. No exemplo abaixo temos a marca ponto usando `Chart.mark_point()`: # In[6]: alt.Chart(df).mark_point() # Todos os pontos foram renderizados um em cima do outro, já que não definimos nada quanto a suas posições. Para separar eles, podemos mapear as dimensões dos dados para uma váriavel visual. Por exemplo, mapear a região do estado para a váriavel visual de posição `y`, que representa a posição `y` dos pontos. Utilizamos o método `encode` para isso: # In[7]: alt.Chart(df).mark_point().encode( y='região', ) # O método `encode()` constrói um mapeamento chave-valor entre as váriaveis visuais (x, y, cor, forma, tamanho, etc.) e os campos dos dados, acessíveis pelo nome do campo. Usando os dataframes do Pandas, Altair tenta inferir automaticamente os tipos de dados. # # Agora podemos separar os pontos que estão agrupados nas regiões, mapeando também a população. # In[8]: alt.Chart(df).mark_point().encode( x='população', y='região', ) # _Conseguimos ver uma concentração de estados na região norte com baixa população, e um dos estados tem muito mais população que todos os outros._ #Clicando nos três pontinhos ao lado do gráfico abre algumas opções, e uma delas é importante para fins de debug, o editor web do Vega. A gramática gerada é enviada junto com os dados para uma outra página, então menos que seu conjunto de dados seja pequeno ou uma URL tente não fazer isso com frequência. Pode tentar com o gráfico acima e ver como fica em formato de gramática.
# ## Tipos de dados # # O componente principal em uma visualização eficiente são os dados. O que é possível fazer com eles e que tipo de mapeamento visual é adequado? # # Altair suporta alguns tipos de dados básicos, e esses tipos podem guiar as decisões de design na visualização, sendo indicado com `Valores temporais medem pontos ou intervalos no tempo. É um tipo especial de valor quantitativo, mas devido a riqueza de contexto e semântica (separação hierárquica, calendários, representação não uniformes) é considerado um tipo totalmente separado. O tipo temporal em Vega-Lite suporta várias transformações temporais (dia, meses, horas, minutos).
# #Exemplos de valores temporais incluem strings de datas como “2019-01-04” e “Jan 04 2019”, assim como o padrão ISO para formato de datas:
`“2019-01-04T17:50:35.643Z”`. Usando Pandas as strings podem ser convertidas para o formato datetime de Python.
Aqui vamos ver alguns exemplos de gráficos mais simples, enquanto apresentamos a combinação das marcas e variáveis visuais. Para isso vamos usar dois conjuntos de dados, o de população dos estados da federação e o arquivo local `dados.csv`, com os dados do INMET do ano de 2019 do estado do Pará por semana, agrupando os valores dos sensores pela média.
# # __Gráfico de barras__ # In[10]: alt.Chart(df).mark_bar().encode( x="estado", y="população" ) # _O que acontece se trocar os as variáveis visuais `x` e `y`?_ # __Gráficos de Linhas__ # In[11]: alt.Chart(dados).mark_line().encode( x="Data:T", y="Precipitação", color="Cidade" # Mapeando cor pela cidade ) # _Em todo as cidades o nível de precipitação diminui no verão, como esperado._ # _O que acontece se não especificar o tipo temporal?_ # **Gráfico de Área** # In[12]: alt.Chart(dados).mark_area().encode( x="Data:T", y="Umidade Relativa do Ar", color="Cidade:N", tooltip="Cidade" # passe o mouse em cima das áreas e agora aparece o nome das cidades ) # _Empillhando as áreas se percebe que nem todas as medições estão sendo feitas em todo momento, tem muitos buracos._ # _O que acontece se trocar a cor do tipo nominal para ordinal?_ # __Gráfico de dispersão - Scatterplot__ # In[13]: alt.Chart(dados).mark_circle(color="blue").encode( alt.X("Temperatura do ar - bulbo seco:Q"), alt.Y("Pressão Atmosférica ao nível da estação:Q"), alt.Fill("Temperatura mínima"), alt.Size("Rajada Máxima de Vento"), alt.OpacityValue(0.3), tooltip=[alt.Tooltip("Cidade"), alt.Tooltip("Data")] ) #Sem indicação, as escalas estão começando do zero, mesmo com valores bem afastados. Um jeito de reverter isso é trocando os argumentos `x` e `y` para `alt.X` e `alt.Y`, que permitem mudanças relacionados a variável visual. Vamos indicar que queremos a escala a partir dos valores, e não do zero.
# In[14]: alt.Chart(dados).mark_circle(color="blue").encode( alt.X("Temperatura do ar - bulbo seco:Q", scale=alt.Scale(zero=False)), alt.Y("Pressão Atmosférica ao nível da estação:Q", scale=alt.Scale(zero=False)), alt.Fill("Temperatura mínima"), alt.Size("Rajada Máxima de Vento"), alt.OpacityValue(0.4), alt.Order("Data"), tooltip=[alt.Tooltip("Cidade"), alt.Tooltip("Data")] ) # _Apesar de estar carregado, com os tooltips tem como ver alguns padrões separados_ # _Definimos `color` com um valor padrão, o que acontece se colocar ele no scatterplot também?_ # ___Small multiples___ # In[15]: alt.Chart(dados).mark_line().encode( alt.X("Data:T"), alt.Y("Umidade Relativa do Ar:Q"), alt.Column("Cidade"), tooltip=[alt.Tooltip("Umidade Relativa do Ar:Q"), alt.Tooltip("Data:T")] ).properties( width=100, height=80 ) # _Trocamos o tamanho da saída para melhor visualizar os padrões, como fica sem essa definição?_ # _O que acontece quando trocamos `Column` por `Row`?_ # ## Exercícios # 1. Adicione tipos explícitos aos gráficos nesse notebook que ainda não tem. Identifique o mais adequado, e na dúvida teste e veja a diferença. # # 1. Crie um _small multiples_ de scatterplots relacionando rajada do vento máxima por radiação global de cada cidade. # # 1. Crie um gráfico de linha usando Data e Temperatura do ponto de orvalho. # # 1. Usando as variáveis visuais `alt.Y1` e `alt.Y2`, crie um gráfico de área com temperatura mínima e temperatura máxima pelo tempo. # # 1. Crie um gráfico com dois atributos nominais na posição e um atributo numérico para cor. Escolha a marca visual mais apropriada. # # 1. Utilizando a base `cars.json` (carregue pela url `https://github.com/vega/vega-datasets/blob/master/data/cars.json`) crie os seguintes gráficos: # # * Gráfico de barras # * Gráfico de linhas # * Scatterplot # * Box plot # * Gráfico de área # # Selecione os atributos adequados para cada gráfico. #