← Back to list

Ciência de Dados e a Fiscalização Municipal

Disciplina: IMD1151 — CIÊNCIAS DE DADOS

Rafael Bezerra da Escóssia · 2021-11-09 12:04 · 2 claps · 9.3 min read
#ufrn #imd #querido-diário #serenata-de-amor #open-knowledge-brasil
Open on Medium ↗

Querido Diário e Ciência de Dados na Fiscalização Pública

Consultando Diários Oficiais na busca de gastos do dinheiro público com remédios não eficazes no combate ao Covid-19

Aqui você encontrará uma pesquisa, sugerida pelo Professor Leonardo Bezerra da disciplina “IMD1151 — Ciência de Dados”, matéria integrante de meu curso de Ciência de Dados na Universidade Federal do Rio Grande do Norte.

Autores desse trabalho: Joseane Palhares, Rafael Bezerra, Wagner Gama

Contextualização

De acordo com o próprio site, a Open Knowledge Brasil (OKBR), também chamada de Rede pelo Conhecimento Livre, é uma Organização da Sociedade Civil (OSC) sem fins lucrativos e apartidária, regida por estatuto. A principal missão da OKBR é desenvolver ferramentas cívicas, projetos, análises de políticas públicas, jornalismo de dados e promover o conhecimento livre nos diversos campos da sociedade. Na esfera política, a organização busca tornar a relação entre governo e sociedade mais próxima e transparente.

Em resumo, a OKBR é uma rede que desenvolve projetos, visando construir uma sociedade mais transparente e inovadora. Nessa perspectiva, um projeto da organização que ganhou grande notoriedade na mídia foi a Operação Serenata de Amor, que é um projeto aberto e colaborativo que utiliza a ciência de dados para fiscalizar os reembolsos efetuados pela Cota para o Exercício da Atividade Parlamentar (CEAP), verba que custeia alimentação, transporte, hospedagem e até despesas com cultura e assinaturas de TV dos deputados federais.

Com o sucesso dessa iniciativa, surgiu a demanda de fiscalizações que transbordem a fronteira de Brasília, que representa apenas uma fatia do orçamento público. Entretanto, ao deparar-se com as esferas municipais, infelizmente, não há muitos dados disponíveis e sem dados não é possível a fiscalização, e é nesse cenário que surge o projeto Querido Diário.

Sendo assim, o Querido Diário objetiva realizar, na esfera municipal, o mesmo que o projeto Serenata de Amor fez na esfera federal. Entretanto, atualmente, os diários oficiais são as principais fontes de informação sobre as prefeituras, encontrando-se, na maioria das vezes, em um formato não estruturado, o que dificulta a exploração das informações. Nesse cenário, o projeto Querido Diário aparece justamente para “libertar” e centralizar essas informações e torná-las mais acessíveis para fiscalização.

O funcionamento da aplicação, de forma resumida, é baseado na realização de scrapings nos sites oficiais das prefeituras e um posterior tratamento de texto.

Neste trabalho, as ferramentas do projeto Querido Diário serão utilizadas para auxiliar na fiscalização da conduta das capitais brasileiras, e outras grandes cidades, em relação a utilização de remédios não eficazes no combate ao covid-19.

Coleta de Dados

O primeiro passo do projeto foi a obtenção dos diários oficiais dos municípios brasileiros, foram selecionadas para esse estudo todas as capitais brasileiras, além de outras grandes cidades do país, veja aqui a lista de municípios contemplados nesse estudo.

O grande desafio dessa primeira fase é automatizar a coleta dos diários oficiais, já que cada prefeitura tem seu próprio portal. Um caminho seria realizar a raspagem dos dados (webscraping) em cada site municipal, entretanto, isso demandaria muito tempo. Nessa perspectiva, para facilitar esse processo, o projeto querido diário já disponibiliza uma API destinada a raspagem dessas informações. A API não possui, ainda, compatibilidade com todos os municípios, entretanto, a maioria das grandes cidades já fazem parte de seu acervo.

Para a utilização da API do querido diário foi necessário, primeiramente, a criação de um ambiente de desenvolvimento. Para isso, clonou-se o repositório do projeto, e acessando o diretório pelo terminal, executou-se os comandos abaixo:

$ python3 -m venv .venv
$ source .venv/bin/activate
$ pip install -r data_collection/requirements-dev.txt
$ pre-commit install

Desse modo, foi criado o ambiente de desenvolvimento através do virtual-env, ativado e instalado todos os requisitos contidos no arquivo requirements-dev.txt.

Após a criação do ambiente virtual e sua ativação, foi executado a aplicação de webscraping para cada município listado. Para isso, foi preciso dirigir-se para o diretório data_collection e executar o seguinte comando:

$ scrapy crawl uf_municipio -a start_date=2020-01-01

Substituindo-se o “uf” pela unidade federativa relativa, da mesma forma com “município”. Por exemplo, para o município de Natal/RN utilizaríamos a seguinte linha de código:

$ scrapy crawl rn_natal -a start_date=2020-01-01

Observe ainda que na pesquisa, filtrou-se a data de início da raspagem, ou seja, foi coletado o diário oficial de todos os municípios da lista, desde o dia 01 de Janeiro de 2020 até a data presente desse texto (01/12/2021). Realizado os scrapings, foram obtidos arquivos PDFs respectivos a cada diário oficial emitido contido no filtro aplicado. Entretanto, foi gerado uma pasta para cada dia, e por questão de organização, foi desejado concentrar todos os arquivos PDFs de um município em uma única pasta.

Para isso, foi executado o seguinte comando no diretório:

find . -name '*.pdf' -exec mv -t ./pdfs {} +

Transformação e Estruturação dos Dados

Como visto anteriormente, o resultado obtido até então são arquivos PDFs relativos aos diários oficiais dos municípios. Entretanto, a extensão .pdf não é a ideal para ser trabalhada. A solução seria transformar os arquivos .pdf em .txt, além de gerar um arquivo .json com os metadados do .pdf.

Para esse processo, o projeto querido diário também fornece os subsídios necessários, através da biblioteca querido-diario-toolbox. Para isso, foi necessário, primeiramente, instalar a biblioteca através do gerenciador de pacotes pip:

$ pip install querido-diario-toolbox

Auxiliado pela biblioteca do querido-diario-toolbox, os seguintes passos foram realizados:

  1. Transformação dos arquivos PDF para TXT e JSON;
  2. Seleção dos diários oficiais que possuem a citação de remédios comprovadamente não eficazes no combate ao COVID (cloroquina, ivermectina, hidroxicloroquina e azitromicina);
  3. Estruturação dos textos relevantes contidos nos arquivos TXT e JSON em um arquivo CSV para futura utilização como DataFrame;
  4. Substituição da coluna com os códigos dos municípios e estados do IBGE por seus respectivos nomes;
  5. Remoção dos textos que não possuem as palavras “COVID”, “CORONA” ou “PANDEMIA”, removendo assim boa parte de textos que apesar de possuirem a citação aos remédios não explicitam sua relação ao covid;
  6. Criação de coluna com os CNPJs das empresas citadas nos textos, quando houver.

Confira os códigos desenvolvidos no repositório do GitHub e o arquivo CSV resultante

Análise Exploratória de Dados

Na análise exploratória de dados, algumas perguntas foram levantadas para conduzir essa etapa. Abaixo, é possível verificar essas perguntas e também suas respectivas respostas:

Quantas vezes cada remédio não eficaz foi citado nos diários oficiais?

Quantas vezes cada município citou um remédio não eficaz?

Quais empresas foram mais citadas?

Todos os códigos utilizados na análise exploratória podem ser vistas aqui.

Preparação dos Dados para Machine Learning

No contexto das informações apresentadas em nosso dataset, não se pode inferir que uma citação a um remédio não eficaz indique necessariamente a sua utilização ao combate do COVID-19, muitas vezes esses remédios são citados em diários oficiais, inclusive, para a crítica de seu uso. Além disso, o objetivo principal dessa pesquisa é encontrar comprovação do gasto de dinheiro público com esses remédios na finalidade de combater o covid-19 e não somente a sua utilização em determinado município. A fim de solucionar esse problema, foi proposto a categorização dos textos em 3 classes de acordo com sua relevância para o estudo:

  1. Texto não comprova a compra
  2. Texto sugere a aquisição dos medicamentos
  3. Texto sugere a aquisição dos medicamentos por dispensa de licitação

É importante notar, o motivo de se dividir a compra dos medicamentos nos itens 2 e 3. O item 3 indica que uma empresa X foi contratada por um município Y para fornecer os medicamentos sem a realização de um processo licitatório, onde ocorre um pregão de preços e etc. Esse tipo de conduta é perigoso e talvez mereça uma atenção melhor e uma investigação mais profunda.

Para a concretização dessa solução, será utilizado algoritmos de machine learning. Mas, antes disso, é necessário realizar a preparação de nosso dataset.

A solução proposta baseia-se no conceito de bag of words, que converte uma coleção de strings em uma matriz e realiza sua contagem. Por exemplo:

>>> from sklearn.feature_extraction.text import CountVectorizer
>>> corpus = [
...     'This is the first document.',
...     'This document is the second document.',
...     'And this is the third one.',
...     'Is this the first document?',
... ]
>>> vectorizer = CountVectorizer()
>>> X = vectorizer.fit_transform(corpus)
>>> vectorizer.get_feature_names_out()
array(['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third',
       'this'], ...)
>>> print(X.toarray())
[[0 1 1 1 0 0 1 0 1]
 [0 2 0 1 0 1 1 0 1]
 [1 0 0 1 1 0 1 1 1]
 [0 1 1 1 0 0 1 0 1]]

Observando a matriz gerada, como resultado, fica fácil de compreender essa função. Observe que temos 4 linhas, que indicam as 4 frases da variável corpus, cada coluna representa uma palavra que segue a ordem [‘and’, ‘document’, ‘first’, ‘is’, ‘one’, ‘second’, ‘the’, ‘third’, ‘this’]. A primeira linha da matriz indica que a primeira frase da variável corpus (‘This is the first document.’) possui:

  • 0 palavras ‘and’
  • 1 palavra ‘document’
  • 1 palavra ‘first’
  • 1 palavra ‘is’
  • 0 palavras ‘one’
  • 0 palavras ‘second’
  • 1 palavra ‘the’
  • 0 palavras ‘third’
  • 1 palavra ‘this’

da mesma forma ocorre para a segunda frase que é a segunda coluna da matriz e assim por diante.

Portanto, para a preparação dos dados na utilização dos algoritmos de machine learning não será necessária a criação de features, uma vez que utilizaremos o conceito de bag of words. Precisamos, entretanto, classificar manualmente essas mensagens, para que o modelo possa ser treinado.

O primeiro passo foi selecionar somente as features necessárias para o aprendizado de maquina, do nosso *dataset* foi selecionado somente a serie “texto”.

Por fim, foi adicionada a coluna “label” que recebe a categoria daquela mensagem. Como já explicado, por se tratar de um modelo supervisionado, a “rotulação” quanto a relevância da mensagem foi manualmente imputada, a partir da leitura de cada mensagem e classificação dela, por fim chegamos ao arquivo preparado para o treinamento do modelo.

Confira o código desenvolvido e o arquivo CSV gerado

Machine Learning na Classificação dos Textos

Carregado o dataset preparado na seção anterior, precisamos treinar o modelo. Mas antes, visando melhorar a interpretação do algoritmo, vamos definir os stop words que serão palavras excluídas no processo de “vetorização” das palavras (normalmente palavras sem significado profundo, comuns da língua). Para essa finalidade, foi utilizado a biblioteca nltk:

import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
stop = stopwords.words('portuguese')

Confira os stop words da língua portuguesa de acordo com a biblioteca nltk:

‘de’, ‘a’, ‘o’, ‘que’, ‘e’, ‘é’, ‘do’, ‘da’, ‘em’, ‘um’, ‘para’, ‘com’, ‘não’, ‘uma’, ‘os’, ‘no’, ‘se’, ‘na’, ‘por’, ‘mais’, ‘as’, ‘dos’, ‘como’, ‘mas’, ‘ao’, ‘ele’, ‘das’, ‘à’, ‘seu’, ‘sua’, ‘ou’, ‘quando’, ‘muito’, ‘nos’, ‘já’, ‘eu’, ‘também’, ‘só’, ‘pelo’, ‘pela’, ‘até’, ‘isso’, ‘ela’, ‘entre’, ‘depois’, ‘sem’, ‘mesmo’, ‘aos’, ‘seus’, ‘quem’, ‘nas’, ‘me’, ‘esse’, ‘eles’, ‘você’, ‘essa’, ‘num’, ‘nem’, ‘suas’, ‘meu’, ‘às’, ‘minha’, ‘numa’, ‘pelos’, ‘elas’, ‘qual’, ‘nós’, ‘lhe’, ‘deles’, ‘essas’, ‘esses’, ‘pelas’, ‘este’, ‘dele’, ‘tu’, ‘te’, ‘vocês’, ‘vos’, ‘lhes’, ‘meus’, ‘minhas’, ‘teu’, ‘tua’, ‘teus’, ‘tuas’, ‘nosso’, ‘nossa’, ‘nossos’, ‘nossas’, ‘dela’, ‘delas’, ‘esta’, ‘estes’, ‘estas’, ‘aquele’, ‘aquela’, ‘aqueles’, ‘aquelas’, ‘isto’, ‘aquilo’, ‘estou’, ‘está’, ‘estamos’, ‘estão’, ‘estive’, ‘esteve’, ‘estivemos’, ‘estiveram’, ‘estava’, ‘estávamos’, ‘estavam’, ‘estivera’, ‘estivéramos’, ‘esteja’, ‘estejamos’, ‘estejam’, ‘estivesse’, ‘estivéssemos’, ‘estivessem’, ‘estiver’, ‘estivermos’, ‘estiverem’, ‘hei’, ‘há’, ‘havemos’, ‘hão’, ‘houve’, ‘houvemos’, ‘houveram’, ‘houvera’, ‘houvéramos’, ‘haja’, ‘hajamos’, ‘hajam’, ‘houvesse’, ‘houvéssemos’, ‘houvessem’, ‘houver’, ‘houvermos’, ‘houverem’, ‘houverei’, ‘houverá’, ‘houveremos’, ‘houverão’, ‘houveria’, ‘houveríamos’, ‘houveriam’, ‘sou’, ‘somos’, ‘são’, ‘era’, ‘éramos’, ‘eram’, ‘fui’, ‘foi’, ‘fomos’, ‘foram’, ‘fora’, ‘fôramos’, ‘seja’, ‘sejamos’, ‘sejam’, ‘fosse’, ‘fôssemos’, ‘fossem’, ‘for’, ‘formos’, ‘forem’, ‘serei’, ‘será’, ‘seremos’, ‘serão’, ‘seria’, ‘seríamos’, ‘seriam’, ‘tenho’, ‘tem’, ‘temos’, ‘tém’, ‘tinha’, ‘tínhamos’, ‘tinham’, ‘tive’, ‘teve’, ‘tivemos’, ‘tiveram’, ‘tivera’, ‘tivéramos’, ‘tenha’, ‘tenhamos’, ‘tenham’, ‘tivesse’, ‘tivéssemos’, ‘tivessem’, ‘tiver’, ‘tivermos’, ‘tiverem’, ‘terei’, ‘terá’, ‘teremos’, ‘terão’, ‘teria’, ‘teríamos’, ‘teriam’.

Com isso, agora podemos realizar a “vetorização” das palavras, separar nosso dataset em treino e teste, definir uma baseline, testar os modelos, alterar parâmetros e enfim obter o modelo final do projeto. Para testar a acurácia dos resultados, foi utilizada a estratégia da estratificação KFold (leia esse artigo para compreender melhor). Abaixo está o resultado das acurácias de algumas funções do scikit-learn que foram testadas, em que o primeiro valor é a acurácia média e entre colchetes está o intervalo de acurácia.

  • Modelo Árvore de Decisão: 96.48% [92.02% ~ 100.00%]
  • Modelo SVC: 90.36% [81.26% ~ 99.45%]
  • Modelo Regressão Logística: 94.33% [83.48% ~ 100.00%]
  • Modelo Random Forest: 94.31% [89.88% ~ 98.74%]
  • Modelo LinearSVC: 95.20% [85.52% ~ 100.00%]
  • Modelo SGDC: 92.56% [82.45% ~ 100.00%]

Portanto, devido a uma melhor acurácia média e menor desvio padrão, o modelo de machine learning utilizado para a previsão do conteúdo de texto presente no diário oficial foi o modelo Árvore de Decisão.

Visualize com mais detalhe o código escrito dessa etapa no link.

Conclusão

Como visto, o objetivo desse trabalho foi indicar possíveis compras dos remédios comprovadamente ineficazes no combate ao Covid-19 pelas prefeituras.

Esse objetivo foi devidamente alcançado, uma vez que os algoritmos de machine learning permitiram uma boa acurácia do resultado na classificação dos textos contidos nos diários oficiais.

Vale salientar que o mesmo pipeline utilizado nesse contexto, poderia ser extrapolado para outras finalidades na fiscalização de órgãos públicos, beneficiando a transparência dessas entidades com a população.


메타데이터
post_id
ebb776c39fda
slug
ciência-de-dados-e-a-fiscalização-municipal-ebb776c39fda
url
https://medium.com/@bezerraescossia/ci%C3%AAncia-de-dados-e-a-fiscaliza%C3%A7%C3%A3o-municipal-ebb776c39fda
canonical_url
https://medium.com/@bezerraescossia/ci%C3%AAncia-de-dados-e-a-fiscaliza%C3%A7%C3%A3o-municipal-ebb776c39fda
author_url
https://medium.com/@bezerraescossia
status
ok
fetched_at
2026-09-02 09:48:20