Como converter texto em datas com pandas em Python
Datas guardadas como texto são uma das causas mais comuns de erros em análises com pandas: ordenações trocadas, filtros que não devolvem nada e gráficos sem sentido. Converter texto em datas com pandas em Python resolve o problema e abre a porta a filtros por período, agrupamentos por mês e cálculos de diferença entre datas. O caminho é sempre o mesmo: pd.to_datetime(), com o formato certo.
Pré-requisitos
- Python 3.9 ou superior instalado
- pandas instalado (
pip install pandas) - Um editor ou notebook (VS Code, Jupyter, Google Colab)
- Noções básicas de DataFrames
Passo 1: Criar um DataFrame de exemplo
Vamos partir de um caso realista: uma lista de encomendas em que a data veio de um CSV e, por isso, chegou como texto. Repare que há uma linha com um valor inválido — é propositado, porque é isso que acontece com dados reais.
import pandas as pd
dados = {
"encomenda": [1001, 1002, 1003, 1004],
"data": ["01/03/2026", "15/03/2026", "02/04/2026", "sem data"],
"valor": [120.5, 80.0, 210.0, 45.0],
}
df = pd.DataFrame(dados)
print(df.dtypes)
O resultado mostra data object. Em pandas, object quer dizer texto. Enquanto a coluna estiver assim, não é possível ordenar cronologicamente nem filtrar por mês.
Passo 2: Converter texto em datas com pd.to_datetime
A função pd.to_datetime() faz a conversão. Como as datas estão no formato europeu (dia primeiro), indicamos dayfirst=True.
df["data"] = pd.to_datetime(df["data"], dayfirst=True)
Se executar isto tal como está, vai obter um erro parecido com ValueError: time data "sem data" doesn't match format. É o comportamento esperado: por omissão, o pandas prefere falhar a inventar uma data. O passo seguinte resolve isto.
Passo 3: Tratar erros com errors="coerce"
Com errors="coerce", tudo o que não for uma data válida passa a NaT (o "valor em falta" das datas), em vez de rebentar o script.
df["data"] = pd.to_datetime(df["data"], dayfirst=True, errors="coerce")
print(df)
A linha 1004 fica com NaT e as restantes ficam convertidas. Nada se perde: o problema fica visível, não escondido.
Passo 4: Indicar o formato exato (mais rápido e mais seguro)
Quando sabe o formato de origem, indique-o com format. É mais rápido em ficheiros grandes e evita interpretações ambíguas, como 03/04 ser lido como 4 de março em vez de 3 de abril.
df["data"] = pd.to_datetime(
df["data_original"],
format="%d/%m/%Y",
errors="coerce",
)
Os códigos mais usados são %d (dia), %m (mês), %Y (ano com 4 dígitos), %H:%M:%S (horas). Para um valor como 2026-03-01 14:30:00, o formato é "%Y-%m-%d %H:%M:%S".
Passo 5: Encontrar as linhas que falharam
Antes de seguir em frente, veja quais as linhas que o pandas não conseguiu converter. Muitas vezes há um padrão (um separador diferente, um cabeçalho repetido a meio do ficheiro).
problemas = df[df["data"].isna()]
print(problemas)
print("Linhas por converter:", len(problemas))
Passo 6: Extrair ano, mês e dia com o acessor .dt
Depois da coluna ser mesmo uma data, o acessor .dt dá acesso a todas as partes do calendário — é aqui que a conversão compensa.
df["ano"] = df["data"].dt.year
df["mes"] = df["data"].dt.month
df["dia_semana"] = df["data"].dt.day_name()
df["mes_ano"] = df["data"].dt.to_period("M")
print(df[["encomenda", "data", "ano", "mes", "dia_semana"]])
Passo 7: Filtrar e agrupar por período
Com datas a sério, filtrar por intervalo e somar por mês torna-se trivial.
inicio = pd.Timestamp("2026-03-01")
fim = pd.Timestamp("2026-03-31")
marco = df[(df["data"] >= inicio) & (df["data"] <= fim)]
print(marco)
por_mes = df.groupby(df["data"].dt.to_period("M"))["valor"].sum()
print(por_mes)
Verificar o resultado
Faça três verificações rápidas:
df.dtypesdeve mostrardatetime64[ns]na colunadata(e já não object).df["data"].isna().sum()indica quantas datas não foram convertidas — o ideal é 0, ou um número que consiga explicar.df["data"].min()edf["data"].max()devem devolver datas plausíveis. Um mínimo em 1970 ou um máximo em 2073 é sinal de formato mal interpretado.
Conclusão
Com pd.to_datetime(), format e errors="coerce" já consegue transformar qualquer coluna de texto numa coluna de datas fiável, encontrar os registos problemáticos e agrupar por período. O passo seguinte natural é explorar df.resample("M") para séries temporais ou pd.date_range() para criar um calendário completo e detetar dias sem vendas. Dica final: se importar sempre o mesmo ficheiro, poupe trabalho e converta logo na leitura, com pd.read_csv("ficheiro.csv", parse_dates=["data"], dayfirst=True). Já sabe qual é o formato exato das datas nos seus ficheiros?