{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introdução, Tipos de dados e Variáveis Visuais\n", "\n", "
Altair é uma bilioteca de visualizações estatísticas declarativas para Python. \n", "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.
\n", "\n", "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.
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sinta-se a vontade para modificar os exemplos, esse é um documento vivo!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para começar, vamos importar as bibliotecas." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import altair as alt\n", "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dados\n", "\n", "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.\n", "\n", "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." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "| \n", " | Cidade | \n", "Data | \n", "Precipitação | \n", "Pressão Atmosférica ao nível da estação | \n", "Pressão Atmosférica máxima | \n", "Pressão Atmosférica mínima | \n", "Radiação Global | \n", "Temperatura do ar - bulbo seco | \n", "Temperatura do ponto de orvalho | \n", "Temperatura máxima | \n", "Temperatura mínima | \n", "Temperatura orvalho máxima | \n", "Temperatura orvalho mínima | \n", "Umidade Relativa máxima | \n", "Umidade Relativa mínima | \n", "Umidade Relativa do Ar | \n", "Direção Horária do Vento | \n", "Rajada Máxima de Vento | \n", "Velocidade Horária do Vento | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "Altamira | \n", "2019-01-06 00:00:00+00:00 | \n", "0.280556 | \n", "989.965278 | \n", "990.274306 | \n", "989.647917 | \n", "894.125641 | \n", "25.822917 | \n", "22.869444 | \n", "26.330556 | \n", "25.337500 | \n", "23.331944 | \n", "22.501389 | \n", "87.416667 | \n", "82.006944 | \n", "84.631944 | \n", "110.173611 | \n", "3.634028 | \n", "1.013889 | \n", "
| 1 | \n", "Altamira | \n", "2019-01-13 00:00:00+00:00 | \n", "0.604762 | \n", "990.213690 | \n", "990.492262 | \n", "989.927381 | \n", "823.916484 | \n", "24.428571 | \n", "22.095833 | \n", "24.861905 | \n", "24.016071 | \n", "22.498214 | \n", "21.716667 | \n", "90.005952 | \n", "85.172619 | \n", "87.684524 | \n", "126.190476 | \n", "2.862500 | \n", "0.835714 | \n", "
| 2 | \n", "Altamira | \n", "2019-01-20 00:00:00+00:00 | \n", "0.103571 | \n", "990.877381 | \n", "991.207143 | \n", "990.555357 | \n", "828.782418 | \n", "24.779762 | \n", "22.383333 | \n", "25.240476 | \n", "24.330357 | \n", "22.810714 | \n", "21.984524 | \n", "89.684524 | \n", "84.553571 | \n", "87.190476 | \n", "137.708333 | \n", "2.890476 | \n", "0.848214 | \n", "
| 3 | \n", "Altamira | \n", "2019-01-27 00:00:00+00:00 | \n", "0.304762 | \n", "990.875595 | \n", "991.179762 | \n", "990.569048 | \n", "882.498901 | \n", "25.006548 | \n", "22.736905 | \n", "25.505357 | \n", "24.580357 | \n", "23.158333 | \n", "22.370238 | \n", "90.214286 | \n", "85.214286 | \n", "87.803571 | \n", "126.994048 | \n", "3.219643 | \n", "0.882738 | \n", "
| 4 | \n", "Altamira | \n", "2019-02-03 00:00:00+00:00 | \n", "0.094048 | \n", "989.825595 | \n", "990.120238 | \n", "989.521429 | \n", "956.195604 | \n", "25.751786 | \n", "22.675595 | \n", "26.236905 | \n", "25.324405 | \n", "23.132143 | \n", "22.314286 | \n", "86.642857 | \n", "81.321429 | \n", "84.029762 | \n", "107.065476 | \n", "3.315476 | \n", "0.951190 | \n", "
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.
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tipos de dados\n", "\n", "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?\n", "\n", "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).
\n", "\n", "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.
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Gráfico de barras__" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(df).mark_bar().encode(\n", " x=\"estado\",\n", " y=\"população\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_O que acontece se trocar os as variáveis visuais `x` e `y`?_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Gráficos de Linhas__" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(dados).mark_line().encode(\n", " x=\"Data:T\",\n", " y=\"Precipitação\",\n", " color=\"Cidade\" # Mapeando cor pela cidade\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Em todo as cidades o nível de precipitação diminui no verão, como esperado._" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_O que acontece se não especificar o tipo temporal?_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Gráfico de Área**" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(dados).mark_area().encode(\n", " x=\"Data:T\",\n", " y=\"Umidade Relativa do Ar\",\n", " color=\"Cidade:N\",\n", " tooltip=\"Cidade\" # passe o mouse em cima das áreas e agora aparece o nome das cidades\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Empillhando as áreas se percebe que nem todas as medições estão sendo feitas em todo momento, tem muitos buracos._" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_O que acontece se trocar a cor do tipo nominal para ordinal?_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Gráfico de dispersão - Scatterplot__" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(dados).mark_circle(color=\"blue\").encode(\n", " alt.X(\"Temperatura do ar - bulbo seco:Q\"),\n", " alt.Y(\"Pressão Atmosférica ao nível da estação:Q\"),\n", " alt.Fill(\"Temperatura mínima\"),\n", " alt.Size(\"Rajada Máxima de Vento\"),\n", " alt.OpacityValue(0.3),\n", " tooltip=[alt.Tooltip(\"Cidade\"),\n", " alt.Tooltip(\"Data\")]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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.
" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(dados).mark_circle(color=\"blue\").encode(\n", " alt.X(\"Temperatura do ar - bulbo seco:Q\", scale=alt.Scale(zero=False)),\n", " alt.Y(\"Pressão Atmosférica ao nível da estação:Q\", scale=alt.Scale(zero=False)),\n", " alt.Fill(\"Temperatura mínima\"),\n", " alt.Size(\"Rajada Máxima de Vento\"),\n", " alt.OpacityValue(0.4),\n", " alt.Order(\"Data\"),\n", " tooltip=[alt.Tooltip(\"Cidade\"),\n", " alt.Tooltip(\"Data\")]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Apesar de estar carregado, com os tooltips tem como ver alguns padrões separados_ " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Definimos `color` com um valor padrão, o que acontece se colocar ele no scatterplot também?_ " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___Small multiples___" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(dados).mark_line().encode(\n", " alt.X(\"Data:T\"),\n", " alt.Y(\"Umidade Relativa do Ar:Q\"),\n", " alt.Column(\"Cidade\"),\n", " tooltip=[alt.Tooltip(\"Umidade Relativa do Ar:Q\"),\n", " alt.Tooltip(\"Data:T\")]\n", ").properties(\n", " width=100,\n", " height=80\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Trocamos o tamanho da saída para melhor visualizar os padrões, como fica sem essa definição?_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_O que acontece quando trocamos `Column` por `Row`?_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercícios" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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. \n", "\n", "1. Crie um _small multiples_ de scatterplots relacionando rajada do vento máxima por radiação global de cada cidade.\n", "\n", "1. Crie um gráfico de linha usando Data e Temperatura do ponto de orvalho.\n", "\n", "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.\n", "\n", "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.\n", "\n", "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: \n", "\n", " * Gráfico de barras\n", " * Gráfico de linhas\n", " * Scatterplot\n", " * Box plot\n", " * Gráfico de área\n", "\n", " Selecione os atributos adequados para cada gráfico.\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.0" } }, "nbformat": 4, "nbformat_minor": 4 }