Na primeira parte desta série, usamos a biblioteca Requests para consultar uma API. Na segunda, transformamos a resposta em um DataFrame e aprendemos a selecionar, filtrar e resumir os dados com Pandas.
Como consumir uma API com Python usando Requests: guia prático
Pandas na prática: como criar e manipular um DataFrame com dados reais
Agora, vamos usar esse mesmo DataFrame para criar visualizações com Matplotlib.
O foco deste artigo será exclusivamente a construção de gráficos. Partiremos de dados já organizados e aprenderemos a criar:
- gráficos de linha;
- gráficos de barras;
- histogramas;
- gráficos de dispersão;
- figuras com mais de um gráfico.
Também veremos como adicionar títulos, rótulos, legendas e grades, formatar datas e salvar as figuras como imagens.
Preparando o ambiente#
No projeto criado nas partes anteriores, adicione o Matplotlib:
uv add matplotlibPara executar o projeto:
uv run main.pyO uv run executa o programa no ambiente do projeto e verifica previamente se as dependências e o arquivo de bloqueio estão sincronizados. ([Astral Docs][1])
No Google Colab, use uma célula de instalação:
%pip install -q matplotlib pandas requestsEm seguida, importe as bibliotecas:
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
import requestsO módulo matplotlib.pyplot será usado para criar as figuras. O módulo matplotlib.dates ajudará a controlar a apresentação das datas no eixo horizontal.
Preparando os dados#
O código abaixo repete apenas a preparação necessária para reconstruir o DataFrame utilizado na parte anterior:
API_URL = "https://air-quality-api.open-meteo.com/v1/air-quality"
PARAMETROS = {
"latitude": -23.5505,
"longitude": -46.6333,
"hourly": (
"european_aqi,"
"pm10,"
"pm2_5,"
"nitrogen_dioxide,"
"ozone"
),
"forecast_days": 3,
"timezone": "America/Sao_Paulo",
}
resposta = requests.get(
API_URL,
params=PARAMETROS,
timeout=30,
)
resposta.raise_for_status()
dados = resposta.json()
df = pd.DataFrame(dados["hourly"])
df["time"] = pd.to_datetime(
df["time"]
)Confira as primeiras linhas:
df.head()Cada linha representa um horário da previsão. As colunas contêm o horário, o índice europeu de qualidade do ar e as concentrações dos poluentes solicitados.
A Air Quality API permite solicitar séries horárias e até sete dias de previsão. Os dados de PM10, PM2.5, dióxido de nitrogênio e ozônio são expressos em microgramas por metro cúbico. ([Open Meteo][2])
Os valores são provenientes de modelos atmosféricos do CAMS. Para uma localização global como São Paulo, a fonte possui resolução espacial aproximada de 45 quilômetros e resolução temporal nativa de três horas. Portanto, os dados não representam necessariamente medições feitas por uma estação instalada exatamente nas coordenadas informadas. ([Open Meteo][2])
A partir daqui, todos os exemplos utilizarão o DataFrame armazenado em df.
Figure e Axes#
Um gráfico criado com Matplotlib normalmente envolve dois objetos principais:
fig, ax = plt.subplots()A variável fig recebe um objeto Figure, que representa a figura completa.
A variável ax recebe um objeto Axes, que representa a área em que os dados serão desenhados. É por meio do Axes que adicionamos linhas, barras, títulos, nomes dos eixos, legendas e grades. ([Matplotlib][3])
Podemos verificar os tipos:
print(type(fig))
print(type(ax))A saída será semelhante a:
<class 'matplotlib.figure.Figure'>
<class 'matplotlib.axes._axes.Axes'>Para exibir a figura:
plt.show()O exemplo completo fica assim:
fig, ax = plt.subplots()
plt.show()Nesse momento, será exibida apenas uma área vazia. Ainda precisamos adicionar os dados ao objeto ax.
Criando um gráfico de linha#
O gráfico de linha é adequado para representar valores ordenados no tempo.
Vamos visualizar a evolução do PM2.5 durante o período consultado:
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
)
plt.show()No método ax.plot(), o primeiro argumento contém os valores do eixo horizontal e o segundo contém os valores do eixo vertical.
ax.plot(
valores_x,
valores_y,
)A documentação do Matplotlib define Axes.plot() como o método usado para representar valores de y em função de x usando linhas e, opcionalmente, marcadores. ([Matplotlib][4])
O argumento figsize define o tamanho da figura em polegadas:
figsize=(11, 5)O primeiro número representa a largura e o segundo, a altura.
O argumento:
layout="constrained"solicita que o Matplotlib ajuste o espaço ocupado por títulos, rótulos e outros elementos para reduzir sobreposições.
Adicionando título e rótulos#
Um gráfico deve informar claramente o que está sendo representado.
Primeiro, recuperamos a unidade do PM2.5 diretamente da resposta da API:
unidade_pm25 = (
dados["hourly_units"]["pm2_5"]
)Agora podemos adicionar o título e os nomes dos eixos:
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
)
ax.set_title(
"Previsão horária de PM2.5 em São Paulo"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"PM2.5 ({unidade_pm25})"
)
plt.show()Os métodos utilizados foram:
ax.set_title()
ax.set_xlabel()
ax.set_ylabel()O título descreve o conteúdo da figura. Os rótulos informam o significado e, quando necessário, a unidade de cada eixo.
Formatando as datas#
O Matplotlib consegue trabalhar com a coluna time porque ela foi convertida para um tipo de data e hora do Pandas.
Entretanto, a exibição automática pode produzir muitos rótulos ou datas difíceis de ler. Podemos controlar onde os marcadores aparecem e como são formatados:
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
)
ax.set_title(
"Previsão horária de PM2.5 em São Paulo"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"PM2.5 ({unidade_pm25})"
)
ax.xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
plt.show()O localizador determina onde os marcadores principais serão colocados:
mdates.HourLocator(interval=12)Nesse caso, exibimos um marcador a cada 12 horas.
O formatador controla a aparência dos rótulos:
mdates.DateFormatter(
"%d/%m\n%H:%M"
)Os códigos utilizados representam:
%d dia
%m mês
%H hora
%M minutoO caractere \n quebra o rótulo em duas linhas. Assim, a data aparece acima do horário.
Adicionando marcadores e grade#
Os pontos individuais da série podem ser destacados com marcadores:
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
marker="o",
markersize=3,
linewidth=1.5,
)
ax.set_title(
"Previsão horária de PM2.5 em São Paulo"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"PM2.5 ({unidade_pm25})"
)
ax.grid(
visible=True,
alpha=0.3,
)
ax.xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
plt.show()O argumento:
marker="o"adiciona um marcador circular em cada observação.
O tamanho dos marcadores é controlado por:
markersize=3A espessura da linha é definida por:
linewidth=1.5A grade é adicionada com:
ax.grid()O parâmetro alpha controla a transparência. Valores próximos de zero deixam o elemento mais transparente, enquanto valores próximos de um o deixam mais opaco.
Comparando duas séries#
É possível adicionar várias linhas ao mesmo Axes.
PM10 e PM2.5 possuem a mesma unidade, portanto podem ser comparados em um único eixo vertical:
unidade_pm = (
dados["hourly_units"]["pm10"]
)fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm10"],
label="PM10",
)
ax.plot(
df["time"],
df["pm2_5"],
label="PM2.5",
)
ax.set_title(
"Previsão horária de material particulado"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"Concentração ({unidade_pm})"
)
ax.legend()
ax.grid(alpha=0.3)
ax.xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
plt.show()Cada chamada a ax.plot() adiciona uma nova série ao gráfico.
O argumento label define o nome da série:
label="PM10"A legenda é exibida com:
ax.legend()A documentação do Matplotlib também recomenda chamadas separadas a plot() como uma forma direta de representar vários conjuntos de dados. ([Matplotlib][4])
Adicionar várias séries ao mesmo gráfico só é adequado quando a comparação faz sentido. Variáveis com unidades ou escalas muito diferentes podem produzir uma visualização confusa.
Destacando a média#
Na parte anterior, usamos o Pandas para calcular a média. Agora, podemos representar esse valor visualmente.
media_pm25 = df["pm2_5"].mean()O método ax.axhline() adiciona uma linha horizontal:
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
label="PM2.5",
)
ax.axhline(
y=media_pm25,
linestyle="--",
label=f"Média: {media_pm25:.2f}",
)
ax.set_title(
"PM2.5 e média do período"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"PM2.5 ({unidade_pm25})"
)
ax.legend()
ax.grid(alpha=0.3)
ax.xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
plt.show()O argumento:
y=media_pm25define a posição vertical da linha.
O estilo tracejado é definido com:
linestyle="--"Na legenda:
f"Média: {media_pm25:.2f}"o especificador :.2f exibe o valor com duas casas decimais.
Criando um gráfico de barras#
Gráficos de barras são úteis para comparar categorias ou períodos discretos.
Como o DataFrame possui muitas observações horárias, vamos calcular a média diária do PM2.5:
df["data"] = df["time"].dt.date
media_diaria = (
df.groupby(
"data",
as_index=False,
)["pm2_5"]
.mean()
)Confira o resultado:
media_diariaAgora, crie o gráfico:
fig, ax = plt.subplots(
figsize=(9, 5),
layout="constrained",
)
ax.bar(
media_diaria["data"].astype(str),
media_diaria["pm2_5"],
)
ax.set_title(
"Média diária de PM2.5"
)
ax.set_xlabel("Data")
ax.set_ylabel(
f"PM2.5 médio ({unidade_pm25})"
)
ax.grid(
axis="y",
alpha=0.3,
)
plt.show()O método:
ax.bar()recebe as categorias no eixo horizontal e os respectivos valores no eixo vertical.
Neste exemplo, as datas foram convertidas para texto:
media_diaria["data"].astype(str)A grade foi aplicada apenas ao eixo vertical:
ax.grid(
axis="y",
alpha=0.3,
)Essa configuração ajuda a comparar as alturas das barras sem adicionar linhas verticais desnecessárias.
Criando um histograma#
Um histograma representa a distribuição de uma variável numérica. Em vez de mostrar cada observação em ordem temporal, ele agrupa os valores em intervalos.
fig, ax = plt.subplots(
figsize=(9, 5),
layout="constrained",
)
ax.hist(
df["pm2_5"].dropna(),
bins=10,
)
ax.set_title(
"Distribuição dos valores de PM2.5"
)
ax.set_xlabel(
f"PM2.5 ({unidade_pm25})"
)
ax.set_ylabel("Frequência")
ax.grid(
axis="y",
alpha=0.3,
)
plt.show()O método:
ax.hist()cria o histograma.
O argumento:
bins=10divide os dados em dez intervalos.
O eixo horizontal representa os valores de PM2.5. O eixo vertical mostra quantas observações foram encontradas em cada intervalo.
Usamos:
df["pm2_5"].dropna()para evitar o envio de valores ausentes ao gráfico.
A quantidade de intervalos influencia a aparência da distribuição. Poucos intervalos produzem uma visão mais resumida; muitos intervalos mostram mais detalhes, mas podem tornar o gráfico fragmentado.
Criando um gráfico de dispersão#
O gráfico de dispersão é usado para observar a relação entre duas variáveis numéricas.
Vamos comparar PM2.5 e PM10:
fig, ax = plt.subplots(
figsize=(8, 6),
layout="constrained",
)
ax.scatter(
df["pm2_5"],
df["pm10"],
alpha=0.7,
)
ax.set_title(
"Relação entre PM2.5 e PM10"
)
ax.set_xlabel(
f"PM2.5 ({unidade_pm25})"
)
ax.set_ylabel(
f"PM10 ({unidade_pm})"
)
ax.grid(alpha=0.3)
plt.show()Cada ponto representa uma linha do DataFrame.
A posição horizontal é determinada pelo PM2.5:
df["pm2_5"]A posição vertical é determinada pelo PM10:
df["pm10"]O gráfico permite observar se valores maiores de uma variável tendem a aparecer junto de valores maiores ou menores da outra.
Entretanto, a aparência de uma relação no gráfico não comprova causalidade. Uma análise estatística mais rigorosa seria necessária para quantificar a associação entre as variáveis.
Usando uma terceira variável#
O tamanho de cada ponto pode representar uma terceira variável.
Vamos utilizar o índice europeu de qualidade do ar:
fig, ax = plt.subplots(
figsize=(8, 6),
layout="constrained",
)
ax.scatter(
df["pm2_5"],
df["pm10"],
s=df["european_aqi"] * 2,
alpha=0.5,
)
ax.set_title(
"PM2.5, PM10 e índice europeu"
)
ax.set_xlabel(
f"PM2.5 ({unidade_pm25})"
)
ax.set_ylabel(
f"PM10 ({unidade_pm})"
)
ax.grid(alpha=0.3)
plt.show()O argumento:
s=df["european_aqi"] * 2define o tamanho dos pontos.
A multiplicação por dois é apenas um ajuste visual. Ela aumenta os marcadores sem modificar os dados armazenados no DataFrame.
Quando o tamanho representa uma variável, essa informação deve ser explicada no título, na legenda ou no texto que acompanha o gráfico.
Criando mais de um gráfico na mesma figura#
Até agora, cada figura continha apenas um Axes.
Também podemos criar uma figura com vários gráficos:
fig, axes = plt.subplots(
nrows=2,
ncols=1,
figsize=(11, 8),
sharex=True,
layout="constrained",
)Nesse caso, axes contém dois objetos:
axes[0]
axes[1]Vamos representar PM2.5 e ozônio separadamente:
unidade_ozonio = (
dados["hourly_units"]["ozone"]
)fig, axes = plt.subplots(
nrows=2,
ncols=1,
figsize=(11, 8),
sharex=True,
layout="constrained",
)
axes[0].plot(
df["time"],
df["pm2_5"],
)
axes[0].set_title("PM2.5")
axes[0].set_ylabel(
unidade_pm25
)
axes[0].grid(alpha=0.3)
axes[1].plot(
df["time"],
df["ozone"],
)
axes[1].set_title("Ozônio")
axes[1].set_xlabel("Data e hora")
axes[1].set_ylabel(
unidade_ozonio
)
axes[1].grid(alpha=0.3)
axes[1].xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
axes[1].xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
plt.show()Os argumentos:
nrows=2
ncols=1criam duas áreas organizadas verticalmente.
O argumento:
sharex=Truefaz com que os dois gráficos compartilhem o mesmo eixo horizontal.
Esse formato é útil quando queremos comparar variáveis no mesmo período sem colocá-las na mesma escala vertical.
Salvando uma figura#
Além de exibir um gráfico, podemos salvá-lo como arquivo.
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
)
ax.set_title(
"Previsão horária de PM2.5 em São Paulo"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"PM2.5 ({unidade_pm25})"
)
ax.xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
fig.savefig(
"previsao-pm25-sao-paulo.png",
dpi=150,
bbox_inches="tight",
)
plt.show()O nome do arquivo determina o formato:
"previsao-pm25-sao-paulo.png"Também seria possível utilizar extensões como .jpg, .svg ou .pdf, de acordo com os formatos suportados pelo ambiente.
O argumento:
dpi=150define a resolução da imagem.
O argumento:
bbox_inches="tight"reduz margens externas desnecessárias.
Para salvar uma imagem com fundo transparente:
fig.savefig(
"previsao-pm25-transparente.png",
dpi=150,
bbox_inches="tight",
transparent=True,
)Em scripts que geram muitas figuras, feche cada uma depois de salvá-la:
plt.close(fig)Isso libera os recursos associados à figura.
Código completo para o projeto com uv#
O arquivo main.py abaixo consulta os dados e salva três gráficos em uma pasta chamada graficos.
from pathlib import Path
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
import requests
API_URL = (
"https://air-quality-api.open-meteo.com"
"/v1/air-quality"
)
PARAMETROS = {
"latitude": -23.5505,
"longitude": -46.6333,
"hourly": (
"european_aqi,"
"pm10,"
"pm2_5,"
"nitrogen_dioxide,"
"ozone"
),
"forecast_days": 3,
"timezone": "America/Sao_Paulo",
}
DIRETORIO_GRAFICOS = Path("graficos")
def consultar_dados() -> dict:
"""Consulta dados horários de qualidade do ar."""
resposta = requests.get(
API_URL,
params=PARAMETROS,
timeout=30,
)
resposta.raise_for_status()
return resposta.json()
def criar_dataframe(
dados: dict,
) -> pd.DataFrame:
"""Converte os dados horários em DataFrame."""
if "hourly" not in dados:
raise KeyError(
"A resposta não contém a chave 'hourly'."
)
df = pd.DataFrame(
dados["hourly"]
)
df["time"] = pd.to_datetime(
df["time"]
)
return df
def formatar_eixo_temporal(ax) -> None:
"""Configura a apresentação das datas."""
ax.xaxis.set_major_locator(
mdates.HourLocator(interval=12)
)
ax.xaxis.set_major_formatter(
mdates.DateFormatter(
"%d/%m\n%H:%M"
)
)
def salvar_grafico_linha(
df: pd.DataFrame,
unidade: str,
) -> None:
"""Salva um gráfico temporal de PM2.5."""
media_pm25 = df["pm2_5"].mean()
fig, ax = plt.subplots(
figsize=(11, 5),
layout="constrained",
)
ax.plot(
df["time"],
df["pm2_5"],
label="PM2.5",
)
ax.axhline(
y=media_pm25,
linestyle="--",
label=f"Média: {media_pm25:.2f}",
)
ax.set_title(
"Previsão horária de PM2.5 "
"em São Paulo"
)
ax.set_xlabel("Data e hora")
ax.set_ylabel(
f"PM2.5 ({unidade})"
)
ax.legend()
ax.grid(alpha=0.3)
formatar_eixo_temporal(ax)
fig.savefig(
DIRETORIO_GRAFICOS
/ "linha-pm25.png",
dpi=150,
bbox_inches="tight",
)
plt.close(fig)
def salvar_histograma(
df: pd.DataFrame,
unidade: str,
) -> None:
"""Salva a distribuição do PM2.5."""
fig, ax = plt.subplots(
figsize=(9, 5),
layout="constrained",
)
ax.hist(
df["pm2_5"].dropna(),
bins=10,
)
ax.set_title(
"Distribuição dos valores de PM2.5"
)
ax.set_xlabel(
f"PM2.5 ({unidade})"
)
ax.set_ylabel("Frequência")
ax.grid(
axis="y",
alpha=0.3,
)
fig.savefig(
DIRETORIO_GRAFICOS
/ "histograma-pm25.png",
dpi=150,
bbox_inches="tight",
)
plt.close(fig)
def salvar_dispersao(
df: pd.DataFrame,
unidade: str,
) -> None:
"""Salva um gráfico de PM2.5 por PM10."""
fig, ax = plt.subplots(
figsize=(8, 6),
layout="constrained",
)
ax.scatter(
df["pm2_5"],
df["pm10"],
alpha=0.7,
)
ax.set_title(
"Relação entre PM2.5 e PM10"
)
ax.set_xlabel(
f"PM2.5 ({unidade})"
)
ax.set_ylabel(
f"PM10 ({unidade})"
)
ax.grid(alpha=0.3)
fig.savefig(
DIRETORIO_GRAFICOS
/ "dispersao-pm.png",
dpi=150,
bbox_inches="tight",
)
plt.close(fig)
def main() -> None:
"""Executa a consulta e cria os gráficos."""
DIRETORIO_GRAFICOS.mkdir(
parents=True,
exist_ok=True,
)
try:
dados = consultar_dados()
df = criar_dataframe(dados)
except requests.exceptions.Timeout:
print(
"A API demorou muito para responder."
)
return
except requests.exceptions.HTTPError as erro:
print(
f"A API devolveu um erro HTTP: {erro}"
)
return
except requests.exceptions.JSONDecodeError:
print(
"A resposta não contém um JSON válido."
)
return
except requests.exceptions.RequestException as erro:
print(
f"Não foi possível consultar a API: "
f"{erro}"
)
return
except (KeyError, ValueError) as erro:
print(
f"Não foi possível preparar os dados: "
f"{erro}"
)
return
unidade_pm = (
dados["hourly_units"]["pm2_5"]
)
salvar_grafico_linha(
df=df,
unidade=unidade_pm,
)
salvar_histograma(
df=df,
unidade=unidade_pm,
)
salvar_dispersao(
df=df,
unidade=unidade_pm,
)
print(
"Gráficos salvos em:"
)
print(
DIRETORIO_GRAFICOS.resolve()
)
if __name__ == "__main__":
main()Execute o programa:
uv run main.pyAo final, a estrutura será semelhante a:
graficos/
├── dispersao-pm.png
├── histograma-pm25.png
└── linha-pm25.pngExercícios#
Alterar a variável do gráfico de linha#
Substitua:
df["pm2_5"]por:
df["ozone"]Atualize também o título, o rótulo e a unidade do eixo vertical.
Criar um gráfico com o maior PM2.5 de cada dia#
Calcule o máximo diário:
df["data"] = df["time"].dt.date
maximo_diario = (
df.groupby(
"data",
as_index=False,
)["pm2_5"]
.max()
)Depois, represente maximo_diario usando ax.bar().
Comparar dióxido de nitrogênio e ozônio#
Adicione as duas séries ao mesmo gráfico:
ax.plot(
df["time"],
df["nitrogen_dioxide"],
label="Dióxido de nitrogênio",
)
ax.plot(
df["time"],
df["ozone"],
label="Ozônio",
)Finalize com:
ax.legend()Alterar os intervalos do histograma#
Compare os resultados produzidos por:
bins=5bins=10bins=20Observe como a escolha muda a apresentação da distribuição.
Representar apenas valores acima da média#
Crie um subconjunto:
media_pm25 = df["pm2_5"].mean()
acima_media = df.loc[
df["pm2_5"] > media_pm25
]Em seguida, use acima_media em um gráfico de linha ou dispersão.
O que aprendemos#
Nesta terceira parte da série, usamos um DataFrame do Pandas para criar visualizações com Matplotlib.
Aprendemos a trabalhar com Figure e Axes, criar gráficos de linha, barras, histogramas e dispersão, comparar séries, destacar médias, formatar datas e organizar mais de um gráfico na mesma figura.
Também aprendemos a salvar os resultados como arquivos de imagem.
A escolha do gráfico deve acompanhar a pergunta feita aos dados:
- gráficos de linha representam evolução ao longo do tempo;
- gráficos de barras comparam categorias ou períodos;
- histogramas mostram distribuições;
- gráficos de dispersão ajudam a observar relações entre variáveis.
Uma visualização não deve apenas tornar os dados mais atraentes. Seu objetivo principal é comunicar uma informação com clareza.
Os valores usados neste artigo continuam sendo previsões produzidas por modelos atmosféricos. Ao publicar os gráficos, inclua a origem dos dados:
Fonte: Open-Meteo Air Quality API, com dados do CAMS Global Atmospheric Composition Forecast.
Referências oficiais#
- Documentação do Matplotlib
- Introdução a Figure e Axes
- Documentação de pyplot.subplots()
- Documentação de Axes.plot()
- Documentação de Axes.bar()
- Documentação de Axes.hist()
- Documentação de Axes.scatter()
- Documentação de Axes.axhline()
- Documentação de Axes.legend()
- Documentação de Axes.grid()
- Documentação de datas no Matplotlib
- Documentação de Figure.savefig()
- Documentação de pyplot.close()
- Open-Meteo Air Quality API
- Projetos com uv
Os destinos correspondem às páginas oficiais do Matplotlib, da Open-Meteo e do uv.