Teste de coordenadas políticas (ou tutorial para o seu primeiro projeto de Data Science)
Nota: uma versão em inglês deste artigo está disponível em “Political compass test (or a tutorial for your first Data Science project)”
Uma das coisas mais fascinantes sobre Data Science é a gigantesca capacidade que ela nos proporciona de responder perguntas — talvez “responder” seja muito pretensioso: vamos dizer “fornecer insights”. Ela utiliza diversos métodos advindos das ciências, com algumas diferenças fundamentais:
- Dados: experimentos tradicionais geralmente são muito custosos na parte de coleta de dados: envolvem laboratórios, preservação de células, reatores que geram altas quantidades de energia, algumas vezes até o sacrifício de animais, dentre outros. Hoje com a internet podemos reaproveitar dados e combinar fontes, possibilitando muito mais a produção de conhecimento;
- Modelos: hoje com o grande poder de processamento dos computadores, os modelos são capazes de perceber padrões sem que nós tenhamos de fornecer hipóteses. Isso facilita o processo de condução de um experimento pois podemos selecionar de forma muito rápida quais padrões merecem uma análise mais detalhada e quais podemos descartar.
Dito isso, proponho aqui um experimento a ser descrito de forma bem detalhada que se refere à política. Há uma série de fatores que tornam esse tema bem interessante para um projeto de Data Science:
- Esse tema é comumente tratado de forma muito subjetiva — sempre influenciado por opiniões de terceiros, análises sobre análises, e uma série de sensacionalismo, fazendo com que a informação sempre chegue de forma muito distorcida ao grande público. Talvez seja interessante ouvir o que os dados têm a nos dizer;
- Como é um assunto de interesse geral — para alguns mais do que para outros, mas todos de alguma forma consomem esse tipo de informação — temos uma vasta base de dados, o que torna a análise bem interessante;
- Da mesma forma, por ser um assunto de grande interesse, temos uma certa base de conhecimento, ainda que de senso comum, nos permitindo avaliar se os resultados são consistentes ou não — sabemos, ainda que grosseiramente, como alguns grupos se comportam, quem está mais próximo ou mais distante ideologicamente de quem e quais pautas são mais ou menos importantes para determinadas frentes.
- E finalmente um aspecto bem prático: os dados que eu encontrei estão bem estruturados. Isso significa que eles podem ser extraídos de forma bem sistemática, ou seja, o dataset é fácil de se obter.
Há uma série vasta de coisas que podemos identificar, como por exemplo: “quais são as épocas do ano mais acirradas politicamente”, “quais partidos votam mais conjuntamente, e quais possuem uma divergência maior entre seus parlamentares”, ou “qual o partido que vota mais diferentemente dos demais”. Todas essas questões são passíveis de análise, e a minha pretensão é passar por algumas delas.
Hora de colocar a mão na massa! Todo o projeto e as etapas aqui mostradas estão documentados na página do GitHub. Para entender o processo, é bom que você tenha algum conhecimento de Python, ou de programação.
Por simplicidade, as demonstrações aqui feitas são as do Senado, já que a parte da Câmara dos Deputados é muito semelhante, evitando assim redundâncias. Mas você pode conferir a Câmara dos Deputados também no projeto do GitHub.
Vamos começar então pela fonte de dados.
Parte 1 — Obtenção dos dados
Os dados foram extraídos das seções da Câmara dos Deputados e do Senado sobre dados abertos. Nelas há diversos ítens — como gastos do orçamento, contratações, e inclusive alguns tutoriais sobre como acessar os próprios dados.
A forma de obtenção dos dados foi através do Web Scraping, acessando esses portais da câmara e salvando o conteúdo obtido. Para exemplificar, vamos acessar a página da agenda do senado, no dia 01/01/2019. Essa página mostra o conteúdo do mês a partir do dia fornecido. Nesse caso, mostra as atividades do mês de janeiro-2019 a partir do dia 1º.
O primeiro destaque em amarelo é a data pois esse é o único parâmetro necessário. Podemos usar a mesma url trocando apenas essa data para obter a agenda completa do senado dos diversos anos.
O segundo destaque é a descrição do evento, que é a recepção do Presidente da República. Nesse caso, por exemplo não houve nenhuma votação — de fato, as atividades parlamentares começam no mês de fevereiro. Vamos ver um caso que inclui votação.
Aqui temos na agenda uma proposta de emenda à constituição (PEC 25/2017), que foi votada em fevereiro. Há diversas descrições sobre o item, como a data em que foi proposta, a apreciação (sessão de discussão ou votação), dentre outros. Mas aqui não há a relação dos senadores e seus votos. Na agenda há somente a descrição dos projetos, mas esses projetos geralmente envolvem discussões e votações, que ocorrem em dias diferentes. A descrição dos votos está em outra página, mas precisamos passar por essa página para obter o código, em laranja. A partir dele buscamos a votação propriamente dita.
Aqui temos a página dessa matéria. Há inicialmente um resumo sobre a votação, indicando seu resultado (Vitória unânime!). Depois temos os votos dos parlamentares, com todos os dados acerca do senador e ao final o seu voto. Vemos, por exemplo, que o senador Jarbas Vasconcelos votou favoravelmente a essa PEC.
Para efetivamente processar esses dados, utilizei uma ferramenta bem famosa para esse tipo de atividade: o Scrapy. Ele possui um conjunto de ferramentas que torna bem simples acessar as páginas, extrair o conteúdo relevante e armazenar os resultados.
Temos inicialmente a url da agenda do Senado. As variáveis são o mês e o ano, que começam em 04/2011. Isso porque é a partir dessa data que as informações estão disponíveis nessa API. Então para cada mês de cada ano, fazemos uma requisição, que vai ser processada pela função parse_agenda.
Essa função é extensa e feita exclusivamente para acessar a agenda do Senado. Mas isso é comum. Cada site tem suas particularidades, como os modos de apresentar a informação, a forma de navegação entre os links, etc. Há inclusive sites que se protegem de quem tenta acessar seu conteúdo por meio desses robôs, usando instrumentos como o reCAPTCHA. Entretanto, como no nosso caso usamos uma base de dados aberta e pública, não há a necessidade de nos preocuparmos com isso.
Parte 2 — Análise exploratória
Aqui começam os gráficos e visualizações. Vamos começar com um bem simples:
O gráfico acima nos diz muito pouco. Esse é um histórico desde 2011 e os partidos mudam bastante — mudam de sigla, se separam, se conglomeram, etc. Mais interessante seria ver isso ao longo do tempo.
Mesmo assim nos parece pouco informativo. Há muitos partidos pequenos, com poucos senadores, que prejudicam a visualização. Para que isso não ocorra, vamos fazer um corte, mantendo os partidos com mais votações e renomeando os outros para ‘outros’. Outra mudança que auxilia muito é a visualização proporcional, ou seja, em vez de observar o total de votos de um partido em um determinado ano, vemos a sua porcentagem de participação no período. Mantendo apenas partidos com mais de 1000 votações ao todo, ficamos assim:
Parte 3 — Principal Component Analysis
Aqui as coisas começam a ficar interessantes.
PCA é um método bastante utilizado surgido nas “ciências tradicionais” para, entre outras coisas, visualização e interpretação dos resultados. Para quem já entende um pouco, é a decomposição da matriz de covariância em seus autovetores, ordenados por seus autovalores que correspondem à variância dos dados em cada autovetor.
Para quem não entende ainda, observe a figura ao lado. Temos uma distribuição em duas dimensões. Observe entretanto que aquela base formada pelas setinhas é muito mais interessante para explicar os dados do que os eixos x e y. Mais interessante que isso: como uma setinha é consideravelmente maior do que a outra, podemos dizer que ela é o componente principal. Dessa forma, uma boa aproximação que podemos fazer é considerar apenas a setinha maior para representar os dados, simplificando a análise. E é isso que faremos com nossos partidos:
Essa matriz corresponde à correlação entre os votos dos partidos. Quanto mais verde é a cor entre dois partidos, mais eles votam um de acordo com o outro. Veja que o ponto de um partido com ele mesmo é sempre o mais verde possível (evidentemente). Em amarelo são os partidos com correlação nula — ou seja, dado o voto de um não há como saber o voto do outro — e em vermelho são os com correlação contrária. Algo digno de nota é que não há nenhuma correlação fortemente negativa entre dois partidos (há alguns pontos que são levemente vermelhos, mas que nem se comparam à força dos verdes). Isso significa que as polarizações políticas não se dão exatamente pelo voto a favor ou contra determinadas pautas, mas sim pela priorização destas.
Aqui apresento-lhes uma outra versão dessa matriz, com algumas modificações:
Foram duas mudanças: a redução dos partidos (apenas os que têm mais de 1000 votações) e a mudança da escala de cor: no primeiro, a escala de vermelho, amarelo e verde está em [-1.0, 0.0, 1.0]; no segundo, em [0.0, 0.5, 1.0]. E aqui já aprendemos uma grande lição:
A forma como os dados são apresentados altera drasticamente sua interpretação.
Veja que, com esse segundo gráfico, já é muito mais difícil dizer que não há uma polarização política. Dá pra ver muito claramente ‘partidos amigos’ e ‘partidos inimigos’. Em suma, é muito fácil utilizar os dados para contar a sua própria versão dos fatos. Cuidado!
Uma outra coisa que fica bem visível em ambos os gráficos é a formação de aglomerados políticos, alguns blocos que costumam votar de forma coesa.
Veja por exemplo, os grupos PSDB e DEM; PP, PL e MDB; e PT e PCdoB. Os dados nos mostram algo simples: a coesão entre esses partidos. Juntando isso ao nosso conhecimento específico, temos uma produção de conhecimento mais interessante. Não sou nenhum especialista em política, mas me arrisco a dizer que isso é uma manifestação do que costumamos chamar respectivamente de direita, centro e esquerda. Vamos aprofundar essa análise.
Parte 4 — As coordenadas políticas
Uma das coisas que me propus a fazer é saber se é possível — sem manipular os dados — visualizar um mapa muito popular, expresso pelo meme ao lado.
A ideia do PCA vem de bom grado para auxiliar nessa tarefa. Dificilmente aparecerá algo tão simples, mas ouso tentar chegar a algum nível de semelhança.
O processo é bem simples: basta fazer a mesma análise mas em vez de obter o principal componente, obtém-se os dois principais componentes.
Sem mais delongas, vamos aos resultados:
A coordenada x é a mesma usada na parte anterior, com a diferença que eu multipliquei por -1 (pura estética, para que os partidos de esquerda fiquem na esquerda e os da direita na direita)
Quanto à coordenada y, me parece que assumindo que se trata do eixo autoritário/liberal, fica parecido com a seguinte figura:
Claro que há diversas ressalvas a serem feitas comparando meu mapa com o da BBC:
- Eles usam um conjunto de leis bem definidas para afirmar o que é liberal, conservador, esquerda e direita, enquanto eu uso apenas PCA;
- A BBC usa os dados dos deputados enquanto eu uso de senadores;
- Essas leis são do período entre 2015–2017, enquanto o período dos dados do Senado é de 2011–2019.
Entretanto, é bem animador conseguir bons resultados com análise relativamente simples. E essa também é uma grande lição:
As vezes é possível atingir bons resultados usando somente técnicas estatísticas tradicionais.
Quando se trata de análises de dados, quanto mais ferramentas dispusermos, melhor. Vamos aplicar um pouco de Machine Learning!
Parte 5 — Classificação dos partidos
A tabela a seguir mostra a relação entre os senadores, seus partidos e as votações. Os números nas linhas são os identificadores dos senadores, de acordo com a API oficial do Senado. A primeira coluna é o partido ao qual o senador pertence e as próximas colunas são os identificadores das matérias — que são as propostas de leis, PEC’s, alterações em leis específicas, etc. Trata-se de um problema bem simples de classificação: temos as colunas que representam as votações, e a coluna target, com o partido do senador. Usei aqui o XGBoost, uma implementação do famoso algoritmo de Gradient Boosting, por ser bem rápido e oferecer algumas visualizações interessantes. O trecho do código é bem simples. Usei a validação cruzada para ter uma noção de acurácia.
Os resultados, no entanto, são péssimos:
0.15625, 0.16129032, 0.24590164, 0.37288136, 0.32142857
Num projeto de Data Science, coisas dão errado. Mais importante do que fazer dar certo, é entender o porquê de ter dado errado. Nesse caso a resposta é bem simples: (302, 832). Essas são as dimensões do dataframe. Há 302 linhas e 832 colunas. Nem precisa hesitar muito para afirmar que é um caso claro de overfitting. Para confirmar isso, basta dar uma olhada na matriz de confusão:
Essa matriz foi feita com o conjunto de dados completo. Isso significa que o modelo foi muito bom para aprender sobre os dados que viu, mas não muito sobre os que não viu. Há uma série de técnicas para melhorar esse modelo — como reduzir o número de colunas, usar regularização, ajustar os hiperparâmetros ou simplesmente trocar por um modelo mais simples. Mas no momento isso não interessa. Há ainda coisas interessantes que o modelo tem a nos mostrar.
A seguir temos os cinco projetos mais importantes para definir o posicionamento político de um senador, e são eles:
- PLV 15/2013 — Reduz a zero as alíquotas da Contribuição para o PIS/PASEP, da COFINS, da Contribuição para o PIS/PASEP — Importação e da COFINS — Importação incidentes sobre a receita decorrente da venda no mercado interno e sobre a importação de produtos que compõem a cesta básica;
- SCD 5/2015 — Regulamenta o art. 7º, parágrafo único, da Constituição Federal (Emenda Constitucional nº 72, de 2013, origem: PEC nº 66, de 2012 — PEC das domésticas);
- MPV 695/2015 — Autoriza o Banco do Brasil S.A. e a Caixa Econômica Federal a adquirirem participação nos termos e condições previstos no art. 2º da Lei nº 11.908, de 3 de março de 2009, e dá outras providências;
- MPV 696/2015 — Extingue e transforma cargos públicos e altera a Lei nº 10.683, de 28 de maio de 2003, que dispõe sobre a organização da Presidência da República e dos Ministérios;
- PLV 7/2012 — Reduz a zero as alíquotas da Contribuição para o PIS/Pasep, da Contribuição para o Financiamento da Seguridade Social — COFINS, da Contribuição para o PIS/Pasep — Importação e da Cofins — Importação incidentes sobre a importação e a receita de venda no mercado interno dos produtos que menciona;
Conclusão
Data Science se trata, no fundo, de explorar possibilidades, testar hipóteses, propor soluções. Não há muitos padrões rígidos a serem seguidos — a criatividade importa bastante. Espero profundamente que esse artigo tenha lhe ajudado a pensar em novas ideias e explorar novos limites. Veja o código!
Bibliografia
- Dados abertos da câmara dos deputados: https://dadosabertos.camara.leg.br/
- Dados abertos da câmara do Senado:
https://www12.senado.leg.br/dados-abertos
- Scrapy Documentation Home Page:
https://docs.scrapy.org/en/latest/
- Principal component analysis
https://en.wikipedia.org/wiki/Principal_component_analysis
- Há partidos políticos no Brasil? — Todas as configurações possíveis
http://www.todasasconfiguracoes.com/2013/09/14/ha-partidos-politicos-no-brasil/
- Direita ou esquerda? Análise de votações indica posição de partidos brasileiros no espectro ideológico — BBC News
https://www.bbc.com/portuguese/brasil-41058120
- Chen, Tianqi and Guestrin, Carlos — XGBoost: A Scalable Tree Boosting System (2016), Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining
https://www.kdd.org/kdd2016/papers/files/rfp0697-chenAemb.pdf