Giter Site home page Giter Site logo

turicas / eleicoes-brasil Goto Github PK

View Code? Open in Web Editor NEW
143.0 13.0 33.0 379 KB

Scripts para capturar dados do Repositório de Dados Eleitorais do TSE, limpá-los, normalizá-los e agrupá-los

License: GNU General Public License v3.0

Python 74.19% Shell 25.81%
dados tse eleicoes2020 hacktoberfest elections brazil opendata

eleicoes-brasil's Introduction

Eleições Brasil

Esse repositório de código contém programas que baixam dados do Tribunal Superior Eleitoral, normalizam, agrupam e limpam. Atualmente as bases de dados disponíveis são:

  • Candidaturas (1996 a 2020)
  • Bens declarados (2006 a 2020)
  • Votação por zona eleitoral (1996 a 2020)
  • Prestação de contas (2002 a 2020)

Metodologia

A fonte primária é o Repositório de Dados Eleitorais do TSE. O processo é o seguinte:

  • Baixar arquivos ZIP
  • Para cada ZIP, extrair (em memória) os arquivos internos
  • Para cada arquivo interno, processá-lo (identificar cabeçalho, limpar)
  • Juntar todos os resultados em um arquivo

Normalização

Algumas etapas de normalização são necessárias para facilitar análises e conversões dos dados, como:

  • Retirar todos os acentos: alguns nomes aparecem com acentos em um ano e sem em outros, dificultando muito os agrupamentos;
  • Retirar strings inúteis: valores como #NULO#, #NULO, #NE e #NE# são retirados, deixando as células em branco;
  • Normalização dos códigos de cargo: os códigos de cargo variam para alguns anos, tornando difícil o agrupamento entre anos e, para facilitar as análises, normalizamos todos os anos;
  • Renomear colunas: nem todas as colunas possuem nomes intuitivos e foram nomeadas (exemplo: COD_SIT_TOT_TURNO foi renomeado para codigo_totalizacao_turno). Para saber mais detalhes sobre as colunas que foram renomeadas, olhe os arquivos no diretório headers/ (caso você altere algum desses arquivos, gere novamente os cabeçalhos finais com python tse.py headers).

Nota: nem todos os códigos/descrição foram normalizados (alguns apresentam inconsistências ainda não resolvidas e serão feitos em breve).

Privacidade

Para garantir a privacidade e evitar SPAM, o script limpa algumas colunas com informações sensíveis. Essa é a forma padrão de funcionamento para não facilitar a exposição desses dados. Os dados censurados são:

  • Na tabela candidatura:
    • A coluna email terá seu conteúdo totalmente limpo
    • A coluna cpf terá os 3 primerios dígitos trocados por *

Caso queira rodar o script sem o modo censura, altere o script run.sh e adicione a opção --no-censorship para o script tse.py.

Instalando

Os programas requerem Python 3.7+. Instale as dependências executando:

pip install -r requirements.txt

Rodando

O script tse.py baixa, trata e extrai os dados. Basta rodá-lo, passando que tipo de dado quer baixar/tratar/extrair:

python tse.py candidatura
python tse.py bem_declarado
python tse.py votacao_zona
python tse.py receita
python tse.py despesa

Os dados ficarão disponíveis em:

  • data/download/: arquivos originais baixados, por ano
  • data/output/: arquivos extraídos (agrupados por tipo)

Caso queira converter os arquivos .csv.gz gerados em um banco de dados SQLite (facilita as análises), execute:

./csv2sqlite.sh

Esse script irá rodar o comando rows csv-to-sqlite em todos os arquivos gerados em data/output e criará o arquivo data/eleicoes-brasil.sqlite.

Opções

As opções listadas abaixo podem ser utilizadas em conjunto.

Anos

Você pode especificar para quais anos deseja a extração (separados por vírgulas), como em:

python tse.py candidatura --years=2014,2018

Alterar fonte dos dados

Como os servidores do TSE podem estar lentos em épocas de eleição, você pode baixar os dados de algum servidor mais rápido que hospede uma cópia deles (chamamos de mirror). No Brasil.IO mantemos um mirror de alguns arquivos do Repositório de Dados Eleitorais do TSE, porém note que ainda não temos uma política de atualização frequente desses dados e, por isso, eles podem estar desatualizados (estamos trabalhando para que sejam atualizados com mais frequência e que a data de cópia dos dados fique explícita em uma página).

Para que o script colete os daos usando nosso mirror, execute-o com a opção --use-mirror:

python tse.py candidatura --use-mirror

Você pode especificar também a URL base do mirror, que por padrão é do Brasil.IO:

python tse.py candidatura --use-mirror --mirror-url=https://data.brasil.io/mirror/eleicoes-brasil/

Apenas baixar

Caso queira apenas baixar os arquivos, utilize a opção --download-only.

Forçar download

Por padrão, caso os arquivos necessários para uma extração já existam em data/download/, eles não serão baixados novamente. Você pode utilizar a opção --force-redownload para que eles sejam deletados e baixados novamente.

Arquivo de saída

Você pode especificar o arquivo de saída (que será sempre um CSV, mas pode estar compactado):

python tse.py candidatura --output=candidatura.csv.gz

Observações

Em alguns casos o TSE libera arquivos compactados no formato RAR (mesmo com a extensão ".zip"). Para extrair os dados desses arquivos você precisa instalar em seu sistema o bsdtar ou unrar (em sistemas Debian e derivados): apt install libarchive-tools ou apt install unrar - o último não é software livre).

Desenvolvendo/contribuindo

Instale as dependências de desenvolvimento:

pip install -r dev-requirements.txt

Rode os testes:

pytest tests.py

Ao alterar os arquivos, rode o comando black . para normalizá-los com relação à PEP-0008.

eleicoes-brasil's People

Contributors

dehatanes avatar diegosouza avatar fmercurio avatar leticiadasilva avatar rhenanbartels avatar turicas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eleicoes-brasil's Issues

Correções nos metadados

  • candidatura:

    • renomear colunas para ficar padronizado, ex: s/nome_municipio/municipio/
    • sigla_uf_nascimento possui valor NAO DIVULGAVEL, trocar para None
    • atualizar schema/candidatura.csv
    • atualizar schema-eleicoes-brasil-candidatura.csv (arquivo de metadados completo, para ser importado no Brasil.IO)
  • filiacao:

    • coluna municipio está com valores trocados da coluna nome
    • atualizar schema/filiacao.csv se necessário
  • receita:

    • nome_doador/nome_doador_originario estão em branco e o campo de CPF/CNPJ correspondente está como -1. Verificar se não deveria ser None e corrigir
    • renomear colunas para ficar padronizado, ex: s/numero_sequencial_candidato/numero_sequencial/
    • fazer schema-eleicoes-brasil-receita.csv (arquivo de metadados completo, para ser importado no Brasil.IO)
    • atualizar schema/receita.csv
  • despesa:

    • renomear colunas para ficar padronizado, se necessário
    • fazer schema-eleicoes-brasil-despesa.csv (arquivo de metadados completo, para ser importado no Brasil.IO)
    • atualizar schema/despesa.csv, se necessário
  • votacao-zona:

    • verificar possibilidade/necessidade de renomear tabela para votacao
    • renomear colunas para ficar padronizado, se necessário
    • fazer schema-eleicoes-brasil-votacao.csv (arquivo de metadados completo, para ser importado no Brasil.IO)
    • atualizar schema/votacao.csv, se necessário
  • documentar metodologia da tabela socio

PermissionError: [WinError 32] O arquivo já está sendo usado por outro processo:

Quando tento executar o código ele apresenta o seguinte erro:

Traceback (most recent call last):
File "tse.py", line 209, in
extract_data(
File "tse.py", line 41, in extract_data
result = extractor.download(year, force=force_redownload)
File "D:\dataScience\perfil_Parlamentar\eleicoes-brasil-master\extractors.py", line 238, in download
file_data = download_file(url, progress=True, chunk_size=256 * 1024)
File "D:\dataScience\anaconda\lib\site-packages\rows\utils_init_.py", line 473, in download_file
os.rename(tmp.name, filename)
PermissionError: [WinError 32] O arquivo já está sendo usado por outro processo: 'C:\Users\Everton\AppData\Local\Temp\tmp3dqrttyw' -> 'C:\Users\Everton\AppData\Local\Temp\tmp3dqrttyw.zip'

Aparentemente é um erro referente a abertura do arquivo zip, parece que por ele não ser fechado acaba gerando essa exception

Já tentei fazer de várias formas mas não sei o que está errado no código ou sou eu que estou fazendo errado?

Limpar datas (filiação partidária)

O arquivo filiacao_parse.py extrai os CSVs de dentro dos ZIPs de filiação partidária, porém as datas estão em formatos diferentes, dependendo do arquivo.
Precisa-se alterar a função convert_row para ela limpar todas as colunas de data. Seria legal adicionarmos testes na função que limpa, para pegar os casos mais comuns.

Extrair CNPJ de campanhas (candidatos e partidos)

[ERRO] ConnectionError: HTTPConnectionPool(host='agencia.tse.jus.br', port=80): Read timed out.

Ao tentar executar a extração da votação de 2018 foi apresentado o seguinte erro

python tse.py votacao-zona --years=2018

`VotacaoZona 2018
Downloading file: 35%|████████████████████ | 276M/796M [05:23<10:08, 854kbytes/s]Traceback (most recent call last):
File "D:\dataScience\anaconda\lib\site-packages\urllib3\response.py", line 436, in _error_catcher
yield
File "D:\dataScience\anaconda\lib\site-packages\urllib3\response.py", line 518, in read
data = self._fp.read(amt) if not fp_closed else b""
File "D:\dataScience\anaconda\lib\http\client.py", line 458, in read
n = self.readinto(b)
File "D:\dataScience\anaconda\lib\http\client.py", line 502, in readinto
n = self.fp.readinto(b)
File "D:\dataScience\anaconda\lib\socket.py", line 669, in readinto
return self._sock.recv_into(b)
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "D:\dataScience\anaconda\lib\site-packages\requests\models.py", line 751, in generate
for chunk in self.raw.stream(chunk_size, decode_content=True):
File "D:\dataScience\anaconda\lib\site-packages\urllib3\response.py", line 575, in stream
data = self.read(amt=amt, decode_content=decode_content)
File "D:\dataScience\anaconda\lib\site-packages\urllib3\response.py", line 540, in read
raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
File "D:\dataScience\anaconda\lib\contextlib.py", line 131, in exit
self.gen.throw(type, value, traceback)
File "D:\dataScience\anaconda\lib\site-packages\urllib3\response.py", line 441, in _error_catcher
raise ReadTimeoutError(self._pool, None, "Read timed out.")
urllib3.exceptions.ReadTimeoutError: HTTPConnectionPool(host='agencia.tse.jus.br', port=80): Read timed out.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "tse.py", line 209, in
extract_data(
File "tse.py", line 41, in extract_data
result = extractor.download(year, force=force_redownload)
File "D:\dataScience\perfil_Parlamentar\eleicoes-brasil-master\extractors.py", line 239, in download
file_data = download_file(url, progress=True, chunk_size=256 * 1024)
File "D:\dataScience\anaconda\lib\site-packages\rows\utils_init_.py", line 447, in download_file
for data in response.iter_content(chunk_size=chunk_size):
File "D:\dataScience\anaconda\lib\site-packages\requests\models.py", line 758, in generate
raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='agencia.tse.jus.br', port=80): Read timed out.
Downloading file: 35%|███▍ | 276M/796M [05:28<10:18, 841kbytes/s]`

É um time-out do cógido request, estou verificando como posso aumentar o time-out para permitir a captura de grandes conjuntos de dados

Erro ao extrair dados de candidatura do ano 2000

Candidatura 2000
  Downloading... file has already been downloaded.
  Extracting...: 1275it [00:00, 3856.18it/s]Traceback (most recent call last):
  File "tse.py", line 155, in <module>
    download_only=args.download_only,
  File "tse.py", line 36, in extract_data
    for row in tqdm(data, desc="  Extracting..."):
  File "/home/rhenanbartels/virtualenvs/eleicoes-brasil/lib/python3.7/site-packages/tqdm/_tqdm.py", line 979, in __iter__
    for obj in iterable:
  File "/home/rhenanbartels/Documents/personal/python/eleicoes-brasil/extractors.py", line 164, in extract
    yield convert_function(row)
  File "/home/rhenanbartels/Documents/personal/python/eleicoes-brasil/extractors.py", line 233, in convert
    new["nome"] = fix_nome(new["nome"])
  File "/home/rhenanbartels/Documents/personal/python/eleicoes-brasil/extractors.py", line 83, in fix_nome
    if value[0] in "',.]":
IndexError: string index out of range

Adicionar script de filiação partidária ao espelho

Rodando o script python tse.py mirror, temos a criação do mirror.sh a partir das URLs geradas nos extractors.py, porém o script filiacao.sh roda num pipeline diferente desse e, por isso, os arquivos de filiação partidária não estão no espelho do Brasil.IO.
Precisamos fazer uma integração (e talvez até uma padronização sobre como gerar o data/download) e então passar a hospedar também os arquivos de filiação partidária.

Erro ao extrair dados rodando para a `receita`.

@turicas, executando o python tse.py receita --years=2014,2016 obtive um erro referente às colunas dos dados terem valores diferentes que as do schema. Erro em detalhe:

PrestacaoContasReceitas 2014
  Downloading... file has already been downloaded.
  Extracting...: 0it [00:00, ?it/s]
Traceback (most recent call last):
  File "tse.py", line 213, in <module>
    extract_data(
  File "tse.py", line 52, in extract_data
    writer.writerow(row)
  File "/usr/lib/python3.8/csv.py", line 154, in writerow
    return self.writer.writerow(self._dict_to_list(rowdict))
  File "/usr/lib/python3.8/csv.py", line 149, in _dict_to_list
    raise ValueError("dict contains fields not in fieldnames: "
ValueError: dict contains fields not in fieldnames: 'codigo_unidade_eleitoral', 'sigla_unidade_federativa_doador', 'numero_candidatura', 'receita', 'nome', 'doador', 'numero_sequencial', 'eleicao', 'doador_originario_receita_federal', 'sigla_unidade_eleitoral', 'codigo_unidade_eleitoral_doador', 'sigla_unidade_federativa', 'doador_receita_federal', 'numero_candidatura_doadora', 'ano', 'sigla_unidade_eleitoral_doador', 'unidade_eleitoral', 'cargo', 'orgao', 'partido', 'partido_doador', 'doador_originario', 'unidade_eleitoral_doador', 'administrador', 'cpf'

Eu reparei que no issue #15 o terceiro check-box tem o campo atualizar schema/receita.csv. Esta tarefa de atualizar o schema que está causando este erro?

De qualquer maneira, como medida paliativa, eu modifiquei a função extract_data do tse.py para filtrar as colunas de cada row para sobrar apenas as list(extractor.schema.keys()) itens do dicionário. Aparentemente o problema foi resolvido e como eu só preciso das colunas que já estão no schema, acho que esta tudo certo. Subi a modificação nesse fork e se você julgar que a alteração é relevante para o projeto, posso mandar o PR.

No mais, excelente trabalho com esses programas que capturam os dados públicos das eleições e dos socios, estão me ajudando muito.

Dados de votação por zona duplicados [2018]

De tempos em tempos o TSE decide atualiza os dados e acaba gerando linhas adicionais dentro dos datasets (CSVs), alterando apenas o campo DT_GERACAO, isso acaba ocasionando inconsistências na base, pois o TSE "mistura" os dados, ao invés de lançar as atualizações em arquivos separados.

Isso acabou ocorrendo com os dados de 2018 (únicos que eu analisei até o momento).

Abaixo seguem exemplos práticos:

Dados filtrados direto da base do TSE

SELECT * 
FROM   votacao_candidato_munzona_raw vcmr 
WHERE  sg_uf = 'AC' 
       AND cd_municipio = '1457' 
       AND nr_zona = '3' 
       AND nr_candidato = '40400'; 

Resultado

id dt_geracao hh_geracao ano_eleicao cd_tipo_eleicao nm_tipo_eleicao nr_turno cd_eleicao ds_eleicao dt_eleicao tp_abrangencia sg_uf sg_ue nm_ue cd_municipio nm_municipio nr_zona cd_cargo ds_cargo sq_candidato nr_candidato nm_candidato nm_urna_candidato nm_social_candidato cd_situacao_candidatura ds_situacao_candidatura cd_detalhe_situacao_cand ds_detalhe_situacao_cand tp_agremiacao nr_partido sg_partido nm_partido sq_coligacao nm_coligacao ds_composicao_coligacao cd_sit_tot_turno ds_sit_tot_turno st_voto_em_transito qt_votos_nominais
5670 13/09/2020 19:12:38 2018 2 Eleição Ordinária 1 297 ELEIÇÕES GERAIS ESTADUAIS 2018 07/10/2018 E AC AC ACRE 1457 SENA MADUREIRA 3 7 Deputado Estadual 10000604794 40400 MÁRCIA MARIA DA SILVA SOUZA MÁRCIA RUFINO #NULO# 12 APTO 2 DEFERIDO Partido isolado 40 PSB Partido Socialista Brasileiro 10000050139 PARTIDO ISOLADO PSB 5 SUPLENTE N 551
2063323 01/08/2019 15:43:50 2018 2 Eleição Ordinária 1 297 ELEIÇÕES GERAIS ESTADUAIS 2018 07/10/2018 E AC AC ACRE 1457 SENA MADUREIRA 3 7 Deputado Estadual 10000604794 40400 MÁRCIA MARIA DA SILVA SOUZA MÁRCIA RUFINO #NULO# 12 APTO 2 DEFERIDO Partido isolado 40 PSB Partido Socialista Brasileiro 10000050139 PARTIDO ISOLADO PSB 5 SUPLENTE N 551

Obs.: verifique que tanto o campo id quanto o campo DT_GERACAO são diferentes, porém o resto das informações são exatamente iguais.

Dados filtrados da base gerada com os dados baixados por esta ferramenta

SELECT * 
FROM   votacao_zona 
WHERE  sigla_uf = 'AC' 
       AND codigo_municipio = '01457' 
       AND numero_zona = '3' 
       AND numero_urna = '40400'; 

Resultado

ano_eleicao codigo_eleicao codigo_tipo_eleicao data_eleicao descricao_eleicao nome_tipo_eleicao tipo_abrangencia_eleicao codigo_totalizacao_turno descricao_totalizacao_turno numero_turno codigo_municipio descricao_ue nome_municipio sigla_ue sigla_uf codigo_legenda composicao_legenda nome_coligacao nome_legenda nome_partido numero_partido numero_sequencial_legenda sigla_partido codigo_cargo codigo_detalhe_situacao_candidatura codigo_situacao_candidatura codigo_situacao_candidatura_superior descricao_cargo descricao_detalhe_situacao_candidatura descricao_situacao_candidatura descricao_situacao_candidatura_superior nome nome_social nome_urna numero_sequencial numero_urna tipo_agremiacao numero_zona total_votos voto_em_transito
2018 297 2 07/10/2018 ELEICOES GERAIS ESTADUAIS 2018 ELEICAO ORDINARIA E 5 SUPLENTE 1 01457 ACRE SENA MADUREIRA AC AC 10000050139 PSB PARTIDO ISOLADO PARTIDO SOCIALISTA BRASILEIRO 40 PSB 7 2 12 DEPUTADO ESTADUAL DEFERIDO APTO MARCIA MARIA DA SILVA SOUZA MARCIA RUFINO 10000604794 40400 PARTIDO ISOLADO 3 551 N
2018 297 2 07/10/2018 ELEICOES GERAIS ESTADUAIS 2018 ELEICAO ORDINARIA E 5 SUPLENTE 1 01457 ACRE SENA MADUREIRA AC AC 10000050139 PSB PARTIDO ISOLADO PARTIDO SOCIALISTA BRASILEIRO 40 PSB 7 2 12 DEPUTADO ESTADUAL DEFERIDO APTO MARCIA MARIA DA SILVA SOUZA MARCIA RUFINO 10000604794 40400 PARTIDO ISOLADO 3 551 N

A mesma situação se repete, porém como não temos as colunas ID nem DT_GERACAO, não é possível filtrar.

Minha sugestão seria validar se existe mais de uma linha para a chave abaixo:

sg_uf
cd_municipio
nr_zona
nr_candidato

Em caso positivo pegar o max(DT_GERACAO) para o registro.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.