Calculando a mediana de idade em arquivos PDF: o que funciona na prática
Você já precisou extrair idades de um relatório em PDF e calcular a mediana? A maioria das pessoas tenta copiar e colar os dados manualmente, perde meia hora e ainda erra. Vou mostrar o jeito que costumo fazer.
idade média resumo pdf
O processo básico envolve três etapas: extração dos dados numéricos do PDF, limpeza e formatação, e cálculo da mediana. Parece simples até você abrir um arquivo que tem tabelas espalhadas por quatro páginas com colunas desalinhadas e células fundidas. Minha ferramenta padrão é um script Python usando pdfplumber para extração e pandas para manipulação. O pdfplumber lida muito melhor com tabelas em PDFs gerados por sistemas antigos — e existem muitos relatórios de RH e cadastros governamentais que ainda vêm assim. O PyPDF2, que muita gente usa por padrão, frequentemente quebra as colunas e mistura os valores quando encontra layouts irregulares.
Aqui está o fluxo que eu sigo. Primeiro, extraio toda a tabela relevante: import pdfplumber
import pandas as pd
with pdfplumber.open("relatorio.pdf") as pdf:
page = pdf.pages[0]
tables = page.extract_tables()
df = pd.DataFrame(tables[0], columns=tables[0][0])
df = df.iloc[1:] remove o cabeçalho repetido
Depois disso vem a parte chata: limpar os dados. Números em PDFs muitas vezes vêm com pontos como separadores de milhar e vírgulas decimais, ou com caracteres invisíveis de espaçamento. O código abaixo resolve isso na prática: df["idade"] = (df["idade"].str.replace(".", "", regex=False)
.str.replace(",", ".", regex=False)
.astype(float))
Para calcular a mediana, é só usar o pandas: mediana = df["idade"].median()
👉 Clique no botão abaixo para saber mais sobre o assunto!
O resultado volta em formato float. Se precisar formatar para um relatório final, uso .round(1) para uma casa decimal, que é o padrão da maioria dos órgãos estatísticos. Um problema real que encontrei recentemente envolveu um PDF de um cadastro municipal onde a coluna de idade estava misturada com observações em texto. A célula continha valores como "45 anos" em vez de apenas "45". O pdfplumber extrai tudo como string, então meu workaround foi aplicar uma regex de extração antes da conversão:
df["idade"] = df["idade"].str.extract(r"(\d+)").astype(float) Isso pegou apenas o primeiro grupo numérico de cada célula, ignorando palavras ao redor. Funciona quando os dados estão sujos assim. Se tiver células em branco ou valores ausentes, o .astype(float) vai gerar NaN, e o pandas trata isso automaticamente no cálculo da mediana — nada de erro, apenas ignora os nulos.
Quanto ao tempo, um arquivo de até 50 páginas com uma tabela principal leva cerca de 2 a 3 minutos para processar inteiro, incluindo limpeza. O gargalo não é o cálculo em si, que é instantâneo, mas a extração e a higienização dos dados. Quanto mais páginas e mais tabelas desorganizadas, mais tempo de ajuste manual você vai precisar. Se você não quer programar, o Excel também consegue fazer o cálculo se conseguir importar os dados. O problema é que a importação de tabelas do PDF pelo Excel frequentemente distorce a estrutura. O Power Query ajuda, mas exige configuração manual para cada tipo de layout diferente. Ainda assim, para arquivos simples com tabelas bem formatadas, é viável e mais rápido do que escrever um script do zero.
Outro detalhe que muita gente perde: a mediana é sensível a outliers apenas na cauda, mas diferente da média, que é afetada por qualquer valor extremo. Em conjuntos de dados demográficos, onde existem registros com idades erradas (como "150 anos" por erro de digitação), a mediana aguenta melhor. Mesmo assim, sempre faço uma validação básica com boxplot ou simplesmente verifico o valor máximo e mínimo antes de finalizar o resumo. print(df["idade"].describe())
Esse comando retorna min, max, quartis e frequência de valores ausentes de uma vez. Leva cinco segundos e evita que você publique um número errado por acidente. Para documentação final em PDF, recomendo usar o reportlab ou weasyprint se quiser gerar o resumo automaticamente a partir dos dados limpos. O weasyprint é mais flexível porque converte HTML/CSS direto para PDF, o que facilita manter um template consistente entre diferentes relatórios.
O que não funciona: tentar usar OCR em PDFs que já são digitais. O pdfplumber extrai o texto nativo diretamente, e o OCR só adiciona tempo e erro de reconhecimento. Use OCR apenas quando o PDF for realmente escaneado, sem camada de texto. Nesse caso, o Tesseract com o pdf2image para rasterizar as páginas antes da extração é o caminho, mas aí o processo sobe para 10 ou 15 minutos por arquivo, dependendo da resolução. Resumindo sem resumir: extraia com pdfplumber, limpe com substituição de strings e regex, calcule a mediana com pandas, valide com describe() e gere o relatório final com weasyprint. O tempo total para um arquivo típico fica entre 3 e 5 minutos, muito abaixo das horas que se gastaCopiando manualmente.