Pandas na prática: como criar e manipular um DataFrame com dados reais#
No artigo anterior, usamos a biblioteca Requests para consultar dados de qualidade do ar por meio de uma API. Conseguimos enviar parâmetros, verificar erros HTTP e converter a resposta recebida em estruturas do Python.
Se ainda não leu o último artigo veja Como consumir uma API com Python usando Requests: guia prático
Agora, vamos avançar para a etapa seguinte: transformar esses dados em uma tabela e explorá-los com o Pandas.
Neste guia, você aprenderá a:
- criar um
DataFrame; - entender linhas, colunas, índice e tipos de dados;
- usar
head(),info()edescribe(); - calcular média, mediana e desvio-padrão;
- selecionar linhas e colunas;
- usar
loceiloc; - criar filtros;
- criar, alterar, renomear e remover colunas;
- ordenar os dados.
Usaremos previsões de qualidade do ar para a cidade de São Paulo. O projeto poderá ser executado localmente com o gerenciador de dependências uv ou diretamente no Google Colab.
O que é o Pandas?#
Pandas é uma biblioteca de código aberto voltada à análise e à manipulação de dados em Python. Ela fornece estruturas que facilitam o trabalho com informações organizadas em linhas e colunas. ([Pandas][1])
As duas estruturas fundamentais da biblioteca são o DataFrame e a Series.
Um DataFrame é uma estrutura bidimensional. Ele se parece com uma tabela, pois possui linhas e colunas.
Uma Series é uma estrutura unidimensional. Na prática, cada coluna de um DataFrame é uma Series. Quando selecionamos uma única coluna, o Pandas devolve uma Series; quando selecionamos várias colunas, o resultado é outro DataFrame. ([Pandas][2])
Importaremos a biblioteca usando a convenção mais comum:
import pandas as pdO nome pd é apenas um apelido que evita escrever pandas repetidamente.
Sobre os dados utilizados#
Usaremos a Air Quality API da Open-Meteo para obter previsões de:
- material particulado PM10;
- material particulado PM2.5;
- dióxido de nitrogênio;
- ozônio;
- índice europeu de qualidade do ar.
A resposta da API contém um objeto hourly. Dentro dele, cada variável é representada por uma lista de valores, acompanhada por uma lista de horários. A resposta também contém hourly_units, que informa as unidades de cada variável. ([Open Meteo][3])
Para PM10, PM2.5, dióxido de nitrogênio e ozônio, as concentrações são expressas em microgramas por metro cúbico, representados por μg/m³. A documentação descreve essas variáveis como concentrações próximas à superfície, aproximadamente 10 metros acima do solo. ([Open Meteo][3])
Esses dados não são medições de uma estação#
Os valores utilizados neste artigo são produzidos por modelos atmosféricos. Eles não representam necessariamente medições feitas por um sensor localizado exatamente nas coordenadas consultadas.
Para São Paulo, a fonte relevante é o CAMS Global Atmospheric Composition Forecast, que possui resolução espacial aproximada de 45 quilômetros e resolução temporal nativa de três horas. O modelo é atualizado a cada 12 horas e fornece até cinco dias de previsão. A API organiza os resultados solicitados em uma série horária. ([Open Meteo][3])
Isso significa que os dados são adequados para aprendizado, exploração e demonstrações de análise, mas não devem ser apresentados como leituras de uma estação local ou usados automaticamente para decisões regulatórias.
O campo european_aqi também merece atenção. Ele representa o índice europeu de qualidade do ar e corresponde ao maior valor entre os índices individuais calculados para diferentes poluentes. Essa classificação não deve ser confundida com índices ou normas ambientais brasileiras. ([Open Meteo][3])
Preparando o ambiente com uv#
O uv pode criar o projeto, registrar as dependências em pyproject.toml, gerenciar o ambiente virtual e manter as versões resolvidas em uv.lock. ([Astral Docs][4])
Crie um novo projeto:
uv init pandas-qualidade-arEntre na pasta:
cd pandas-qualidade-arAdicione o Pandas e o Requests:
uv add pandas requestsO comando uv add registra as bibliotecas como dependências do projeto.
Ao final do artigo, você encontrará um main.py completo. Para executá-lo:
uv run main.pyAntes de executar o programa, o uv run verifica se o ambiente e o arquivo de bloqueio estão sincronizados com as dependências declaradas no projeto. ([Astral Docs][4])
Preparando o Google Colab#
O Google Colab é um ambiente hospedado de notebooks Jupyter. Ele permite executar código Python no navegador sem configurar um ambiente local. ([Google Pesquisa][5])
Crie um novo notebook e use uma célula exclusiva para instalar as dependências:
%pip install -q pandas requestsNão vamos concentrar todo o notebook em uma única célula. Cada bloco de código apresentado nas próximas seções pode ser colocado em uma célula separada.
A organização recomendada será:
Célula 1 — instalação
Célula 2 — importações e configurações
Célula 3 — função de consulta
Célula 4 — execução da requisição
Célula 5 — inspeção do JSON
Célula 6 — criação do DataFrame
Célula 7 — inspeção do DataFrame
Célula 8 — seleção de linhas e colunas
Célula 9 — estatísticas
Célula 10 — filtros
Célula 11 — criação e alteração de colunas
Célula 12 — ordenação e resultado finalImportando as bibliotecas#
Em uma nova célula do Colab ou no início do arquivo Python, importe as bibliotecas:
import pandas as pd
import requestsConfigurando a consulta#
Vamos usar as coordenadas aproximadas da cidade de São Paulo:
API_URL = "https://air-quality-api.open-meteo.com/v1/air-quality"
LATITUDE = -23.5505
LONGITUDE = -46.6333
VARIAVEIS = (
"european_aqi",
"pm10",
"pm2_5",
"nitrogen_dioxide",
"ozone",
)Usaremos três dias de previsões. Isso gera observações suficientes para praticar filtros e estatísticas sem tornar o exemplo desnecessariamente grande.
A API permite controlar o período por meio de forecast_days, aceitando até sete dias. Quando o parâmetro não é informado, o padrão é cinco dias. ([Open Meteo][3])
Criando a função de consulta#
Em outra célula, defina a função:
def consultar_qualidade_ar(
latitude: float,
longitude: float,
) -> dict:
"""Consulta previsões horárias de qualidade do ar."""
parametros = {
"latitude": latitude,
"longitude": longitude,
"hourly": ",".join(VARIAVEIS),
"forecast_days": 3,
"timezone": "America/Sao_Paulo",
"domains": "cams_global",
}
resposta = requests.get(
API_URL,
params=parametros,
timeout=30,
)
resposta.raise_for_status()
return resposta.json()O parâmetro hourly informa quais variáveis devem ser devolvidas como séries horárias.
A expressão:
",".join(VARIAVEIS)transforma a tupla em uma string:
european_aqi,pm10,pm2_5,nitrogen_dioxide,ozoneO parâmetro timezone solicita horários no fuso America/Sao_Paulo. Segundo a documentação da API, quando um fuso é informado, os horários são devolvidos no horário local e os dados começam à meia-noite local. ([Open Meteo][3])
Executando a requisição#
Em uma nova célula:
try:
dados = consultar_qualidade_ar(
latitude=LATITUDE,
longitude=LONGITUDE,
)
except requests.exceptions.Timeout as erro:
raise RuntimeError(
"A API demorou muito para responder."
) from erro
except requests.exceptions.HTTPError as erro:
raise RuntimeError(
f"A API devolveu um erro HTTP: {erro}"
) from erro
except requests.exceptions.JSONDecodeError as erro:
raise RuntimeError(
"A resposta não contém um JSON válido."
) from erro
except requests.exceptions.RequestException as erro:
raise RuntimeError(
f"Não foi possível consultar a API: {erro}"
) from erroEm um notebook, lançar uma exceção interrompe a execução. Isso evita que as células seguintes tentem usar uma variável dados que não foi criada corretamente.
Inspecionando a resposta#
Antes de criar o DataFrame, devemos observar a estrutura recebida.
dados.keys()A resposta deverá conter chaves semelhantes a:
dict_keys([
'latitude',
'longitude',
'generationtime_ms',
'utc_offset_seconds',
'timezone',
'timezone_abbreviation',
'elevation',
'hourly_units',
'hourly'
])Agora, inspecione as chaves dos dados horários:
dados["hourly"].keys()O resultado será semelhante a:
dict_keys([
'time',
'european_aqi',
'pm10',
'pm2_5',
'nitrogen_dioxide',
'ozone'
])Também podemos visualizar as unidades:
dados["hourly_units"]A estrutura de hourly é adequada à criação de um DataFrame: cada chave será transformada em uma coluna, enquanto os elementos de mesma posição nas listas formarão uma linha. A documentação da API especifica que os horários são devolvidos em uma lista e cada variável em um vetor de valores. ([Open Meteo][3])
Criando o DataFrame#
Agora podemos criar a tabela:
df = pd.DataFrame(dados["hourly"])No Colab, deixe df como última expressão da célula:
dfIsso produz uma visualização tabular mais adequada do que:
print(df)Cada linha representa um horário. Cada coluna representa uma variável.
Visualizando as primeiras linhas#
Para visualizar as cinco primeiras linhas:
df.head()Para visualizar as dez primeiras:
df.head(10)Para visualizar as últimas:
df.tail()O método head() devolve as primeiras linhas e é útil para verificar rapidamente se os dados possuem o formato esperado. ([Pandas][6])
Conhecendo o tamanho do DataFrame#
Use o atributo shape:
df.shapeO resultado possui o formato:
(quantidade_de_linhas, quantidade_de_colunas)Por exemplo:
(72, 6)O valor exato deve ser verificado na execução, mas três dias de valores horários normalmente produzem 72 registros.
Observe que shape é um atributo, não um método. Portanto, não usamos parênteses.
Conhecendo as colunas e o índice#
Para visualizar os nomes das colunas:
df.columnsPara visualizar o índice:
df.indexO índice padrão geralmente começa em zero:
RangeIndex(start=0, stop=72, step=1)O índice identifica as linhas do DataFrame. Ele não precisa ser uma coluna dos dados.
Verificando os tipos#
Use:
df.dtypesInicialmente, a coluna time provavelmente será apresentada como str ou object, pois os horários chegaram no JSON como texto.
Para obter um resumo mais completo:
df.info()O método info() mostra as colunas, seus tipos, a quantidade de valores não ausentes e informações sobre uso de memória. ([Pandas][7])
Convertendo a coluna de data e hora#
Para trabalhar corretamente com datas, converta time:
df["time"] = pd.to_datetime(df["time"])A função pd.to_datetime() converte valores escalares, listas, arrays ou Series em objetos de data e hora do Pandas. ([Pandas][8])
Confirme a alteração:
df.dtypesAgora a coluna deverá apresentar um tipo semelhante a:
datetime64[us]O tipo exato pode variar conforme a versão e o ambiente.
Selecionando uma coluna#
Para selecionar somente PM2.5:
df["pm2_5"]Verifique o tipo:
type(df["pm2_5"])O resultado será uma Series:
pandas.SeriesCada coluna de um DataFrame é uma Series. ([Pandas][2])
Selecionando várias colunas#
Para selecionar data, PM2.5 e PM10:
df[["time", "pm2_5", "pm10"]]Agora o resultado é outro DataFrame:
type(df[["time", "pm2_5", "pm10"]])Resultado:
pandas.DataFrameAo selecionar várias colunas, usamos uma lista dentro dos colchetes externos. ([Pandas][2])
Selecionando linhas com iloc#
O iloc trabalha com posições inteiras. A contagem começa em zero. ([Pandas][9])
Selecione a primeira linha:
df.iloc[0]Selecione as cinco primeiras linhas:
df.iloc[:5]Selecione as cinco primeiras linhas e as três primeiras colunas:
df.iloc[:5, :3]No último exemplo:
df.iloc[linhas, colunas]O primeiro seletor controla as linhas e o segundo controla as colunas.
Como os intervalos seguem as regras comuns do Python, :5 seleciona as posições de zero a quatro.
Selecionando linhas e colunas com loc#
O loc trabalha principalmente com rótulos do índice e nomes de colunas. Ele também aceita condições booleanas. ([Pandas][10])
Selecione a linha cujo índice é zero:
df.loc[0]Selecione um valor específico:
df.loc[0, "pm2_5"]Selecione as linhas de índice zero até quatro e duas colunas:
df.loc[0:4, ["time", "pm2_5"]]Há uma diferença importante: no loc, o limite final do intervalo é incluído. Portanto, 0:4 inclui a linha de índice quatro. ([Pandas][10])
Calculando a média#
A média do PM2.5 pode ser calculada assim:
media_pm25 = df["pm2_5"].mean()
media_pm25Para arredondar o resultado:
round(media_pm25, 2)Também podemos calcular a média de várias colunas:
colunas_concentracao = [
"pm10",
"pm2_5",
"nitrogen_dioxide",
"ozone",
]
df[colunas_concentracao].mean().round(2)O resultado é uma Series contendo a média de cada coluna.
Calculando a mediana#
A mediana é o valor central dos dados após sua ordenação:
df["pm2_5"].median()A mediana pode ser menos influenciada por valores extremos do que a média.
Calculando o desvio-padrão#
Use:
df["pm2_5"].std()Para várias colunas:
df[colunas_concentracao].std().round(2)Por padrão, std() calcula o desvio-padrão amostral, usando divisor N - 1. Esse comportamento pode ser alterado pelo argumento ddof. ([Pandas][11])
Para calcular o desvio-padrão populacional:
df["pm2_5"].std(ddof=0)Para este artigo, manteremos o comportamento padrão do Pandas.
Mínimo e máximo#
Para encontrar o menor valor:
df["pm2_5"].min()Para encontrar o maior:
df["pm2_5"].max()Também podemos encontrar o índice da linha com o maior PM2.5:
indice_maior_pm25 = df["pm2_5"].idxmax()
indice_maior_pm25E selecionar a linha completa:
df.loc[indice_maior_pm25]Resumindo os dados com describe()#
O método describe() reúne várias estatísticas:
df[colunas_concentracao].describe().round(2)Para colunas numéricas, a saída normalmente contém:
count: quantidade de valores não ausentes.
mean: média.
std: desvio-padrão.
min: menor valor.
25%: primeiro quartil.
50%: mediana.
75%: terceiro quartil.
max: maior valor.
A documentação define describe() como um método para gerar estatísticas descritivas de tendência central, dispersão e formato da distribuição, desconsiderando valores NaN. Por padrão, ele apresenta os percentis de 25%, 50% e 75%. ([Pandas][12])
Não incluímos european_aqi na lista de concentrações porque ele é um índice, e não uma concentração medida em μg/m³.
Criando um filtro básico#
Vamos selecionar os horários em que o PM2.5 está acima da média do período.
Primeiro, crie a condição:
media_pm25 = df["pm2_5"].mean()
filtro_pm25 = df["pm2_5"] > media_pm25Visualize a condição:
filtro_pm25.head()O resultado é uma Series de valores booleanos:
0 False
1 False
2 True
3 True
4 FalseAgora aplique o filtro:
df_acima_media = df.loc[filtro_pm25].copy()
df_acima_media.head()Usamos .copy() porque pretendemos tratar o resultado como um novo conjunto de dados independente.
Filtrando e selecionando colunas#
Podemos aplicar o filtro e escolher apenas algumas colunas:
df.loc[
df["pm2_5"] > media_pm25,
["time", "pm2_5", "pm10"],
]Esse comando combina:
- seleção por condição;
- seleção de linhas;
- seleção de colunas.
Combinando condições#
Para selecionar horários em que PM2.5 e ozônio estão acima de suas respectivas médias:
media_ozonio = df["ozone"].mean()
filtro_combinado = (
(df["pm2_5"] > media_pm25)
& (df["ozone"] > media_ozonio)
)
df.loc[
filtro_combinado,
["time", "pm2_5", "ozone"],
]O operador & representa “e”.
Para selecionar registros que atendam a pelo menos uma das condições:
filtro_alternativo = (
(df["pm2_5"] > media_pm25)
| (df["ozone"] > media_ozonio)
)
df.loc[filtro_alternativo]O operador | representa “ou”.
Cada condição deve ficar entre parênteses.
Filtrando um intervalo#
O método between() facilita filtros entre dois valores:
df.loc[
df["european_aqi"].between(20, 40),
["time", "european_aqi"],
]Esse exemplo seleciona valores do índice europeu entre 20 e 40.
A classificação pertence ao índice europeu e não deve ser tratada como uma classificação oficial brasileira. Segundo a Open-Meteo, o intervalo acima de 20 até 40 corresponde à categoria europeia “fair”, geralmente traduzida como razoável. ([Open Meteo][3])
Criando novas colunas#
Podemos criar uma coluna contendo apenas a data:
df["data"] = df["time"].dt.dateOutra com a hora:
df["hora"] = df["time"].dt.hourVisualize o resultado:
df[["time", "data", "hora"]].head()Também podemos criar uma coluna com base em um cálculo:
df["diferenca_pm"] = df["pm10"] - df["pm2_5"]Ou uma coluna booleana:
df["pm2_5_acima_da_media"] = (
df["pm2_5"] > media_pm25
)Confira:
df[
[
"time",
"pm10",
"pm2_5",
"diferenca_pm",
"pm2_5_acima_da_media",
]
].head()Alterando valores de uma coluna#
Podemos arredondar todas as concentrações:
df[colunas_concentracao] = (
df[colunas_concentracao].round(2)
)Nesse caso, estamos substituindo as colunas existentes por suas versões arredondadas.
Também podemos criar uma coluna de texto e alterar apenas determinadas linhas:
df["periodo"] = "noturno"
df.loc[
df["hora"].between(6, 17),
"periodo",
] = "diurno"Agora:
df[["time", "hora", "periodo"]].head(20)A primeira atribuição preenche toda a coluna com "noturno". Depois, o loc altera somente as linhas cuja hora está entre 6 e 17.
Renomeando colunas#
O método rename() pode receber um dicionário com os nomes antigos e novos:
df_renomeado = df.rename(
columns={
"time": "data_hora",
"nitrogen_dioxide": "no2",
"ozone": "o3",
}
)Confira:
df_renomeado.columnsPor padrão, rename() devolve um novo objeto. Os rótulos que não aparecem no dicionário permanecem inalterados. ([Pandas][13])
Removendo colunas#
Para remover uma coluna:
df_sem_diferenca = df.drop(
columns=["diferenca_pm"]
)Para remover várias:
df_reduzido = df.drop(
columns=[
"diferenca_pm",
"pm2_5_acima_da_media",
"periodo",
]
)O método drop() remove linhas ou colunas por seus rótulos. Como seu comportamento padrão devolve um novo DataFrame, armazenamos o resultado em outra variável. ([Pandas][14])
Removendo linhas#
Para remover a primeira linha pelo índice:
df_sem_primeira_linha = df.drop(
index=df.index[0]
)Isso não altera o df original.
Para manter a alteração:
df = df.drop(
index=df.index[0]
)Em análises reais, uma linha não deve ser removida apenas por estar no início ou no fim. O exemplo serve para demonstrar a sintaxe.
Ordenando os dados#
Para ordenar do menor para o maior PM2.5:
df.sort_values(
by="pm2_5",
)Para colocar os maiores valores primeiro:
df_ordenado = df.sort_values(
by="pm2_5",
ascending=False,
)
df_ordenado.head()O método sort_values() ordena os registros de acordo com uma ou mais colunas. O argumento ascending=False solicita ordem decrescente. ([Pandas][15])
Também podemos usar:
df.nlargest(
5,
"pm2_5",
)Esse comando devolve as cinco linhas com maiores valores de PM2.5.
Resultado final da análise#
Vamos criar uma tabela com os dez horários de maior PM2.5:
maiores_valores_pm25 = (
df.loc[
:,
[
"time",
"pm2_5",
"pm10",
"ozone",
"european_aqi",
],
]
.sort_values(
by="pm2_5",
ascending=False,
)
.head(10)
)
maiores_valores_pm25Também podemos apresentar o resumo estatístico:
resumo_estatistico = (
df[colunas_concentracao]
.describe()
.round(2)
)
resumo_estatisticoAssim, terminamos o exercício com dois resultados:
- os dez horários com maior previsão de PM2.5;
- um resumo estatístico das concentrações consultadas.
Código completo para projeto com uv#
Substitua o conteúdo de main.py pelo código abaixo:
import pandas as pd
import requests
API_URL = "https://air-quality-api.open-meteo.com/v1/air-quality"
LATITUDE = -23.5505
LONGITUDE = -46.6333
VARIAVEIS = (
"european_aqi",
"pm10",
"pm2_5",
"nitrogen_dioxide",
"ozone",
)
COLUNAS_CONCENTRACAO = [
"pm10",
"pm2_5",
"nitrogen_dioxide",
"ozone",
]
def consultar_qualidade_ar(
latitude: float,
longitude: float,
) -> dict:
"""Consulta previsões horárias de qualidade do ar."""
parametros = {
"latitude": latitude,
"longitude": longitude,
"hourly": ",".join(VARIAVEIS),
"forecast_days": 3,
"timezone": "America/Sao_Paulo",
"domains": "cams_global",
}
resposta = requests.get(
API_URL,
params=parametros,
timeout=30,
)
resposta.raise_for_status()
return resposta.json()
def criar_dataframe(dados: dict) -> pd.DataFrame:
"""Transforma os dados horários em um 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 preparar_dataframe(
df: pd.DataFrame,
) -> pd.DataFrame:
"""Cria colunas auxiliares para a análise."""
df = df.copy()
media_pm25 = df["pm2_5"].mean()
df["data"] = df["time"].dt.date
df["hora"] = df["time"].dt.hour
df["diferenca_pm"] = (
df["pm10"] - df["pm2_5"]
)
df["pm2_5_acima_da_media"] = (
df["pm2_5"] > media_pm25
)
df["periodo"] = "noturno"
df.loc[
df["hora"].between(6, 17),
"periodo",
] = "diurno"
df[COLUNAS_CONCENTRACAO] = (
df[COLUNAS_CONCENTRACAO].round(2)
)
return df
def exibir_resultados(
df: pd.DataFrame,
dados: dict,
) -> None:
"""Exibe informações e resultados da análise."""
print("Dados de qualidade do ar")
print("=" * 50)
print(
"Célula do modelo:",
dados["latitude"],
dados["longitude"],
)
print("Fuso horário:", dados["timezone"])
print("Dimensões do DataFrame:", df.shape)
print("\nTipos das colunas:")
print(df.dtypes)
print("\nPrimeiras linhas:")
print(df.head())
print("\nMédias:")
print(
df[COLUNAS_CONCENTRACAO]
.mean()
.round(2)
)
print("\nDesvios-padrão:")
print(
df[COLUNAS_CONCENTRACAO]
.std()
.round(2)
)
print("\nResumo estatístico:")
print(
df[COLUNAS_CONCENTRACAO]
.describe()
.round(2)
)
maiores_valores = (
df.loc[
:,
[
"time",
"pm2_5",
"pm10",
"ozone",
"european_aqi",
],
]
.sort_values(
by="pm2_5",
ascending=False,
)
.head(10)
)
print("\nDez maiores valores de PM2.5:")
print(maiores_valores.to_string(index=False))
def main() -> None:
try:
dados = consultar_qualidade_ar(
latitude=LATITUDE,
longitude=LONGITUDE,
)
df = criar_dataframe(dados)
df = preparar_dataframe(df)
except requests.exceptions.Timeout:
print("A API demorou muito para responder.")
except requests.exceptions.HTTPError as erro:
print("A API devolveu um erro HTTP.")
print(erro)
except requests.exceptions.JSONDecodeError:
print("A resposta não contém um JSON válido.")
except requests.exceptions.RequestException as erro:
print("Não foi possível consultar a API.")
print(erro)
except (KeyError, ValueError) as erro:
print("Não foi possível preparar os dados.")
print(erro)
else:
exibir_resultados(
df=df,
dados=dados,
)
if __name__ == "__main__":
main()Execute:
uv run main.pyExercícios para praticar#
Depois de executar o código, tente realizar estas modificações:
Consultar outra cidade#
Altere:
LATITUDE = -22.9068
LONGITUDE = -43.1729As coordenadas acima apontam aproximadamente para o Rio de Janeiro.
Consultar sete dias#
Altere o parâmetro:
"forecast_days": 7,A API permite até sete dias de previsão. ([Open Meteo][3])
Encontrar os cinco maiores valores de ozônio#
df.nlargest(
5,
"ozone",
)[["time", "ozone"]]Selecionar somente o período diurno#
df_diurno = df.loc[
df["periodo"] == "diurno"
].copy()Calcular a média apenas do período diurno#
df_diurno[
COLUNAS_CONCENTRACAO
].mean().round(2)Selecionar o primeiro dia da previsão#
primeira_data = df["data"].min()
df_primeiro_dia = df.loc[
df["data"] == primeira_data
].copy()O que aprendemos#
Neste artigo, transformamos a resposta de uma API em um DataFrame e exploramos os principais recursos introdutórios do Pandas.
Aprendemos a:
- criar um
DataFramea partir de um dicionário; - inspecionar linhas, colunas, tipos e dimensões;
- converter texto em data e hora;
- diferenciar
SerieseDataFrame; - selecionar dados com colchetes,
loceiloc; - calcular média, mediana, mínimo, máximo e desvio-padrão;
- gerar estatísticas descritivas com
describe(); - aplicar filtros booleanos;
- combinar condições;
- criar e modificar colunas;
- remover linhas e colunas;
- ordenar registros.
Também observamos uma regra essencial da análise de dados: antes de calcular estatísticas, precisamos entender o que cada variável representa.
Os valores usados aqui são previsões produzidas por um modelo atmosférico. Eles não são necessariamente medições de uma estação local, e o índice europeu de qualidade do ar não corresponde automaticamente às classificações adotadas no Brasil.
Ao publicar resultados produzidos com essa API, inclua uma atribuição clara à Open-Meteo e ao provedor CAMS, conforme solicitado na documentação. ([Open Meteo][3])
Uma atribuição simples pode ser:
Fonte dos dados: Open-Meteo Air Quality API, com dados do CAMS Global Atmospheric Composition Forecast.
No próximo artigo, podemos avançar para o tratamento de valores ausentes, duplicidades e inconsistências antes de iniciar análises mais complexas.
Referências oficiais#
- Pandas — documentação oficial
- Pandas — seleção de subconjuntos de dados
- Open-Meteo — Air Quality API
- Astral — gerenciamento de projetos com uv
- Google Colab — perguntas frequentes
- Pandas — DataFrame.head()
- Pandas — DataFrame.info()
- Pandas — pandas.to_datetime()
- Pandas — DataFrame.iloc
- Pandas — DataFrame.loc
- Pandas — Series.std()
- Pandas — DataFrame.describe()
- Pandas — DataFrame.rename()
- Pandas — DataFrame.drop()
- Pandas — DataFrame.sort_values()