Como transformar um PDF em uma base de dados

Estudo de caso passo-a-passo com os últimos resultados do Programa de Avaliação Seriada (PAS) da Universidade de Brasília (UnB)

Guilherme Viana
Data Hackers
6 min readJun 14, 2019

--

Este tutorial tem os seguintes pré-requisitos:

  • Nível intermediário em R;
  • Familiaridade com o pacote tidyverse, em especial dplyr e stringr, assim como com o operador %>%;
  • Conhecimento básico de regex (regular expressions).

Sobre o PAS — Programa de Avaliação Seriada

O PAS — Programa de Avaliação Seriada é uma das formas de ingresso no ensino superior na Universidade de Brasília, implementado desde 1996. Sua diferença está na palavra-chave “seriada” — os futuros universitários fazem uma prova ao final de cada ano do ensino médio, e fazem a opção de qual curso desejam na última etapa, concorrendo para conseguir uma das mais de 4.000 vagas ofertadas todos os anos.

A seleção seriada ocorre anualmente. A edição de 2018, por exemplo, tem sua primeira avaliação ao final do ano, na qual os estudantes do 1º ano do Ensino Médio fazem a prova da 1ª Etapa do PAS. Neste tutorial trabalharemos com dados referentes a esse grupo de alunos.

A fonte dos dados

Os resultados da 1ª etapa do PAS de 2018 foram divulgados >aqui<. Após baixarmos e abrirmos o arquivo, vemos que é um PDF normal, no estilo relatório, com uma breve introdução seguida por uma enxurrada de nomes e números, que correspondem aos números de inscrição, notas e nomes dos candidatos.

Print screen da primeira página do relatório

Como nosso objetivo é criar uma base de dados das notas dos candidatos, não há que se falar na simples conversão de PDF para Excel, pois teríamos o mesmo problema: um arquivo sem tratamento, porém em outra extensão. Dessa forma fica clara a importância e necessidade de uma ferramenta mais poderosa e adequada — [que na minha preferência é] o R.

Preciso analisar os resultados, mas estão em PDF! E agora?

Essa é a realidade de muitos profissionais que trabalham com dados, pois a maioria dos arquivos publicados online está nos formatos HTML ou PDF. Não é à toa que diversos sites dedicam-se à tarefa de conversão do PDF para outros formatos, como o ilovepdf, que costumava ser minha primeira opção nesses momentos de necessidade.

Mas e quando não dá certo? Ou melhor, quando não queremos a simples conversão entre formatos, mas sim as informações contidas no PDF em um formato tratado e utilizável, como uma base de dados? Aí a nossa melhor opção é programar.

Leitura e processamento de PDFs no R

Vamos utilizar dois pacotes: o tidyverse e o pdftools. O primeiro é, na verdade, uma coleção de pacotes que trabalham bem em conjunto. Eu, particularmente, já tenho o costume de utilizá-lo, mas caso você prefira utilizar apenas o estritamente necessário, dplyr e stringr são as estrelas aqui. Já o pdftools é um dos pacotes disponíveis para a leitura de PDFs. Para aqueles que ainda não os têm instalados:

Ok! Pacotes instalados, arquivo baixado na pasta de trabalho correta (atalho Ctrl + Shift + H, no RStudio, para escolher o diretório de trabalho), podemos começar. O primeiro passo é carregar os pacotes necessários e fazer a leitura do PDF, usando a função pdf_text.

Esse comando gerou o elemento texto_bruto, que, se verificarmos, é um vetor de texto com uma coluna e 331 linhas — ou seja, a função pdf_text leu cada página em uma linha distinta. Podemos trabalhar assim, porém seria ideal se cada observação representasse uma linha do texto, de forma a permitir um código mais fluido e compreensível. Para tanto, utilizamos a função strsplit para separar o texto de acordo com a expressão regular \n, que é o código que representa a quebra de linha. O produto disso será uma lista, então usamos a função unlist para voltar ao formato de vetor. Por último transformamos esse vetor em nossa primeira versão da base de dados, com a função enframe.

Certo. Os dados estão em um formato mais amigável, mas longe ainda de serem considerados tratados. Agora devemos começar a parte de mineração de texto, que é a limpeza e tratamento desses pedaços de texto. Vamos começar pelo mais simples — ao visualizarmos o elemento texto_bruto, vemos que as primeiras quinze linhas não têm informações relevantes ao nosso objetivo, logo, vamos excluí-las, assim como as dez últimas linhas.

Feito isso, precisamos recorrer às expressões regulares para continuar a limpeza. Um site que descobri e que gosto de utilizar é o regex101, pois ele permite testar, de forma rápida e sem precisar ficar executando código no RStudio, diversas combinações de regex até que você consiga a correspondência necessária. Dito isso, podemos voltar ao arquivo original para observar quais partes do texto não devem continuar. O primeiro ponto que reparei são os números de página, no rodapé de todas as folhas. E no fim do arquivo temos texto sobressalente também:

Print das linhas que devemos retirar

Traduzindo essa interpretação para código, temos o seguinte:

Aparentemente, então, tudo indo muito bem. Temos apenas o texto estritamente necessário, em um formato maleável. Agora nos falta colocar cada informação em seu quadrado, certo? De acordo com o Edital, a ordem das informações é a seguinte:

… número de inscrição, nome do candidato em ordem alfabética, escore bruto na parte 1, escore bruto na parte 2, somatório dos escores brutos nas partes 1 e 2, nota final nos itens do tipo D e nota final na prova de redação em Língua Portuguesa.

Nossa base de dados final terá, então, sete colunas e muitas linhas. Parece que acabamos com a parte de limpeza, então vamos continuar a formatação. Primeiro passo seria juntar em uma única linha todas as linhas do texto_limpo, de forma a possibilitar a quebra por aluno e, depois, por variável. A separação dos alunos será feita graças ao delimitador “\” presente no PDF, e as variáveis serão delimitadas com facilidade pela “,”.

Mas ops! O RStudio avisou que ocorreu um erro na linha 22660… O que deu errado?

3.096. 18117113 não parece uma nota válida

Analisando o resultado, parece que alguém ficou de fora da nossa ordenação — o candidato 18117113. Voltando ao PDF original, vemos que é a primeira pessoa logo após as linhas que limpamos, da última página. Ok… e? Vamos voltar um pouco e achar essa pessoa.

Limpeza e tratamento dos dados é um processo recursivo

O print nos mostrou que há uma linha com dois candidatos, mesmo após a quebra — ou seja, está faltando o delimitador do candidato 18117113. Vamos resolver isso e executar todo o código novamente.

A seção de “limpeza dos dados” foi atualizada

Sem avisos de erro por parte do RStudio, então parece que deu certo! Inspecionando o elemento texto_final_limpo, temos o esperado: muitas linhas (22.669, para ser exato) e sete colunas. Uma rápida inspeção mostra que ainda faltou uma pequena limpeza a ser feita: tem um ponto no último número:

Não acaba, é isso?

Há também outro detalhe:

os números não são exatamente números, primeiro porque estão armazenados como texto, e segundo pois o separador decimal deveria ser a vírgula, e não o ponto.

Vamos arrumar esses detalhes então.

Acaba sim. A limpeza e formatação. Para poder começar a análise.

Agora sim! Temos a base de dados prometida desde o título deste artigo.

Considerações finais

Minha intenção com este estudo de caso foi mostrar o fluxo de trabalho que segui desde a identificação do problema (arquivo em PDF) até sua resolução (base de dados). Importante frisar que esta é apenas a primeira etapa em todos os projetos relacionados a dados. Apenas após a devida preparação das informações, por meio da limpeza e do tratamento, é que estamos aptos a iniciar a próxima fase, de exploração dos dados.

E é justamente isso que pretendo fazer no próximo artigo: explorar as informações obtidas e construir um aplicativo shiny que permita aos candidatos a consulta de suas notas, já com a comparação de seu desempenho relativo a todos os participantes.

Obrigado por ficar até o fim, e até a próxima!

Meus contatos: IG, Twitter, GitHub

--

--

Guilherme Viana
Data Hackers

Estatístico, mestre em Adm, doutorando em Economia na UnB. Principais interesses: programação com R, análise & visualização de dados, dogs e jogos de RPG