Na prática, dados raramente chegam limpos. Valores nulos, duplicatas, colunas mal nomeadas, tipos errados — limpar um DataFrame com Pandas é a etapa que antecede qualquer análise confiável. Este artigo cobre as transformações mais frequentes no trabalho real de um analista.
Filtrando linhas
import pandas as pd
df = pd.read_csv("vendas.csv")
# Filtro simples:
df_sul = df[df["regiao"] == "Sul"]
# Múltiplas condições (use & para E, | para OU):
df_premium = df[(df["valor"] > 5000) & (df["status"] == "Entregue")]
# isin(): filtrar por lista de valores
df_sp_rj = df[df["estado"].isin(["SP", "RJ"])]
# ~: negação (NOT)
df_sem_cancelado = df[~(df["status"] == "Cancelado")]
# query(): sintaxe mais legível
df_sul = df.query("regiao == 'Sul' and valor > 1000")
Tratando valores nulos
# Verificar nulos:
print(df.isnull().sum())
# Remover linhas com qualquer nulo:
df_limpo = df.dropna()
# Remover apenas se nulo em colunas específicas:
df_limpo = df.dropna(subset=["valor", "cliente"])
# Preencher nulos com um valor:
df["valor"] = df["valor"].fillna(0)
df["regiao"] = df["regiao"].fillna("Não informado")
# Preencher com a mediana (para números):
df["valor"] = df["valor"].fillna(df["valor"].median())
Removendo duplicatas
# Remover linhas 100% duplicadas:
df = df.drop_duplicates()
# Manter a primeira ocorrência baseado em uma coluna chave:
df = df.drop_duplicates(subset=["id_pedido"], keep="first")
Renomeando e selecionando colunas
# Renomear:
df = df.rename(columns={
"Valor Total": "valor_total",
"Nome do Cliente": "cliente"
})
# Selecionar colunas específicas:
df = df[["id_pedido", "cliente", "valor_total", "data"]]
# Remover colunas:
df = df.drop(columns=["coluna_inutil", "outra_coluna"])
Criando colunas derivadas
# Coluna calculada:
df["comissao"] = df["valor"] * 0.05
# Coluna condicional com numpy.where:
import numpy as np
df["categoria"] = np.where(df["valor"] >= 5000, "Premium", "Standard")
# Múltiplas condições com numpy.select:
condicoes = [df["valor"] >= 5000, df["valor"] >= 2000, df["valor"] >= 500]
categorias = ["Ouro", "Prata", "Bronze"]
df["categoria"] = np.select(condicoes, categorias, default="Sem categoria")
# apply(): lógica Python arbitrária por linha
def classifica(row):
if row["valor"] > 5000 and row["regiao"] == "Sul":
return "Sul Premium"
return "Outros"
df["segmento"] = df.apply(classifica, axis=1)
Convertendo tipos de dados
df["valor"] = pd.to_numeric(df["valor"], errors="coerce")
df["data"] = pd.to_datetime(df["data"], dayfirst=True)
df["categoria"] = df["categoria"].astype("category")
# Extraindo partes de datas:
df["ano"] = df["data"].dt.year
df["mes"] = df["data"].dt.month
df["dia_semana"] = df["data"].dt.day_name()
Perguntas frequentes
Por que devo usar .copy() ao criar um subconjunto do DataFrame?
Sem .copy(), modificar o subconjunto pode gerar o aviso "SettingWithCopyWarning" e às vezes modificar o DataFrame original. Use df_sub = df[df["col"] == valor].copy() para garantir independência.
query() ou filtro com colchetes?
Para condições simples, query() é mais legível. Para condições complexas com variáveis Python, use colchetes: df[df["valor"] > limite] onde limite é uma variável.