import pandas as pdimport seaborn as snsimport matplotlib.pyplot as plt
C:\Users\julio\miniconda3\lib\site-packages\scipy\__init__.py:177: UserWarning: A NumPy version >=1.18.5 and <1.26.0 is required for this version of SciPy (detected version 1.26.4
warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion}"
Nessa parte, nosso interesse é trabalhar na escolha das melhores visualizações para nossos dados, e como implementar isso usando a biblioteca seaborn.
Por que isso é importante? Além de realizar análises de dados, precisamos nos preparar para comunicar resultados. Boas visualizações são essenciais para isso. A necessidade de comunicar dados pode acontecer dentro do dos seus estudos de direito, mas também em situações de negócios, como apresentações para clientes e visual law.
4.1.1 O que é?
Visualização de dados é a representação de dados em gráficos, tabelas e diagramas que podem ser interpretados por pessoas. Trata-se de uma área interdisciplinar, misturando estatística, arte e comunicação. É uma parte da área de data storytelling, que envolve organizar todos os resultados de uma análise de dados em uma ordem lógica para comunicar de forma efetiva com a audiência.
4.1.2 Por que fazer?
Visualizações estão presentes na grande maioria dos projetos de ciência de dados. Além disso, é a parte mais acessível da ciência de dados do ponto de vista de quem lê. Mostrar uma visualização costuma ser mais efetivo do que a saída de um modelo ou uma fórmula. Finalmente, é uma das partes mais difíceis de automatizar da ciência de dados. Uma carreira em dataviz dificilmente ficará obsoleta.
4.1.3 Para que servem?
Uma base de dados contém toda a informação que precisamos. No entanto, não somos capazes de tirar conclusões apenas olhando essas bases. Por isso, é necessário resumir esses dados em estatísticas, como vimos na apostila sobre medidas de posição e variabilidade. Nem sempre as estatísticas (os números) são úteis para uma comunicação efetiva… Por isso, faz sentido mostrá-las usando formas, cores e outros elementos que facilitam a absorção da informação pelas pessoas.
4.1.4 Em que momento utilizamos?
Abaixo, temos o ciclo da ciência de dados. Esse diagrama foi adaptado do livro R para ciência de dados, que é uma referência para quem quer aprender ciência de dados com R.
Esse ciclo resume a maioria das tarefas que precisamos executar ao longo de um projeto de ciência de dados. Começamos pela importação, que envolve a leitura de dados de diferentes fontes. Em seguida, limpamos e transformamos esses dados para que possam ser usados em análises. A etapa de análise é um ciclo em si, envolvendo transformação de dados (criação de colunas e agregações), a visualização dos dados e a aplicação de modelos estatísticos / de machine learning para entender os dados. Finalmente, precisamos comunicar os resultados ou automatizar nosso produto de dados.
Note que a visualização de dados aparece em duas partes principais: Visualizar e Comunicar.
Na parte de visualização, estamos fazendo uma análise exploratória dos dados. Isso significa que estamos tentando entender os dados, e não necessariamente comunicar resultados. É um trabalho de investigação, que precisa ser rápido de fazer. O objetivo principal é aprender.
Na parte de comunicação, estamos fazendo um trabalho de otimização visual. Agora, nosso objetivo é comunicar os resultados com outras pessoas. Isso significa que precisamos de gráficos mais bonitos, mais explicativos e mais fáceis de entender. O trabalho deve, inclusive, ser encaixado em um fluxo de storytelling. O objetivo principal é comunicar.
O seaborn é uma biblioteca que é muito efetiva para fazer gráficos de análise exploratória. Para otimização visual, ela é um pouco limitada. No entanto, é possível fazer gráficos muito bonitos com ela, e é uma biblioteca muito fácil de usar. Por isso, é uma ótima escolha para começar a aprender visualização de dados. Se tiver interesse em estudar uma ferramenta mais robusta, recomendamos o ggplot2 do R, que é uma das melhores ferramentas para otimização visual.
A partir de agora, vamos retomar os nossos conceitos de tipos de variáveis e descrever as melhores visualizações para cada combinação de tipos de variáveis.
Uma referência legal nesse sentido é o site From Data to Viz, que é um guia para escolher a melhor visualização para os seus dados.
Vamos tratar dos seguintes exemplos:
Visualizações para variáveis categóricas
Gráficos univariados
Gráficos bivariados
Com outra categórica
Com variável numérica
Visualizações para variáveis numéricas
Gráficos univariados
Gráficos bivariados
Com variável categórica
Com outra numérica
Primeiro vamos falar de exploração, depois vamos dar um exemplo de otimização visual.
4.2 Visualizações para variáveis categóricas
Os gráficos univariados de variáveis categóricas são os mais comuns em ciência de dados no direito, já que o tipo de variável mais comum é a categórica.
4.2.1 Univariada
A função mais comum para visualizar variáveis categóricas é o countplot. Esse gráfico é uma versão do barplot do matplotlib, mas com a contagem de cada categoria no eixo y.
sns.countplot(data=camaras, x='decisao')
Veja que os rótulos ficaram sobrepostos. Outra forma de visualizar é rotacionando o eixo:
sns.countplot(data=camaras, y='decisao')
Agora está um pouco melhor. Em alguns lugares, existe uma distinção entre ‘gráficos de barras’ (o segundo caso) e ‘gráficos de colunas’ (o primeiro caso), mas essa distinção não é importante.
Se nosso interesse é mostrar a proporção e não os valores absolutos, podemos usar o barplot do seaborn:
Também podemos ordenar as barras para facilitar a leitura. Geralmente fazemos isso apenas para nominais, não para ordinais.
E se quisermos mostrar a proporção em vez da contagem? Podemos calcular essas proporções com o pandas e usar o barplot. Nesse caso, eu não precisei nem ordenar, porque os dados já estão ordenados do jeito que eu quero.
Na verdade, tanto o countplot quanto o barplot são versões do catplot com kind='count' e kind='bar', respectivamente. O catplot é uma função mais flexível, que permite que façamos gráficos de barras com mais de uma variável categórica.
Veja a imagem abaixo retirada da documentação do seaborn:
sns.catplot(data=contagens, y='decisao', x ='prop', kind='bar')
Como o catplot é mais flexível, ele é a função que vamos usar para fazer gráficos bivariados com variáveis categóricas.
Por último, temos os gráficos de pizza ou donut. Eles podem ser úteis para mostrar proporções, mas são menos efetivos do que os gráficos de barras. A razão é que é mais difícil comparar setores/ângulos do que comprimentos. No entanto, eles são muito populares em apresentações de negócios. No seaborn, não temos uma função específica para fazer gráficos de pizza, mas podemos usar o pie do matplotlib.
Quando temos duas variáveis categóricas, temos várias escolhas de visualizações possíveis para os gráficos de barras. Os mais comuns são i) separar por cores e colocar as barras lado a lado; ii) separar por cores e empilhar as barras; e iii) criar sub-gráficos para cada categoria.
O seaborn não possui uma forma fácil de fazer as barras empilhadas. Por isso, utilizamos o matplotlib mesmo. Para isso, no entanto, precisamos montar uma base pivotada.
Quando temos a variável de interesse categórica e a explicativa numérica, é um pouco difícil de criar visualizações, porque no fundo o que queremos entender é como o aumento/diminuição dessa variável numérica afeta a probabilidade de um evento relacionado à variável categórica acontecer. Isso geralmente é feito através de modelos estatísticos como a regressão logística, que veremos mais para frente na disciplina.
Algumas alternativas são: i) categorizar a variável numérica – nesse caso, voltamos ao que já vimos anteriormente; ii) analisar a distribuição da variável numérica para cada categoria – nesse caso, é como se estivéssemos invertendo qual é a variável de interesse e qual é a variável explicativa, logo isso faz parte da seção de variáveis numéricas, que veremos ainda nessa apostila, mas mais para frente.
4.3 Visualização para variáveis numéricas
4.3.1 Univariada
A análise univariada de uma variável de interesse numérica geralmente busca entender a distribuição dos dados.
Existem três principais visualizações aqui: histograma, densidade e boxplot. A densidade é simplesmente uma versão suavizada do histograma, e é possível mostrar os dois ao mesmo tempo.
sns.displot(camaras, x='tempo')
Podemos mudar o número de barras com os parâmetros bins (quantidade de barras) ou binwidth (largura da barra).
sns.displot(camaras, x='tempo', bins=30)
sns.displot(camaras, x='tempo', binwidth=1)
sns.displot(camaras, x='tempo', kind='kde')
Veja que, nesse caso, o eixo y representa a densidade, e não as contagens. A densidade tem relação com o conceito de distribuição de probabilidades. Na verdade, essa densidade é uma estimativa da função densidade de probabilidades da variável estudada (ou seja, é um modelo estatístico!). A área total do gráfico é 1.
Abaixo, juntamos histograma e densidade
# com o gráfico de distribuiçãosns.displot(camaras, x='tempo', kde=True)
Finalmente, temos o boxplot. O boxplot pode ser usado no caso univariado, mas é mais comum quando temos uma variável explicativa categórica.
sns.boxplot(camaras, x='tempo')
4.3.2 Bivariada: explicativa categórica
A ideia aqui é simplesmente repetir os gráficos acima para a variável categórica de interesse.
# alternativa ao boxplot: violinplot# trata-se basicamente de um gráfico de densidade duplicado. Fica bonitinho.camaras_sem_extraord = camaras[~camaras['extraord']].sort_values('camara')sns.violinplot(data=camaras_sem_extraord, x='tempo', y='camara')
4.3.3 Bivariada: explicativa numérica
Quando temos duas variáveis numéricas, usualmente fazemos um gráfico de dispersão. Nesse caso, usamos o relplot() do seaborn.
Um tipo especial de análise bivariada é quando o eixo x é uma data. Nesse caso, temos uma série de tempo, e representsaos os dados com um gráfico de linhas.
# vamos calcular a proporção de negados ao longo do tempo# criando uma coluna que pega a data de publicação e arredonda o trimestre# o pandas é bem burocrático para fazer essa tarefa simplescamaras['periodo'] = pd.to_datetime(camaras['dt_publicacao']).dt.to_period('Q').dt.to_timestamp()prop_negados_mes = ( camaras .query('polo_mp == "Passivo"') .groupby('periodo') .agg(prop_negados = ('decisao', lambda x: (x =='Negaram').mean())) .reset_index())prop_negados_messns.relplot(prop_negados_mes, x='periodo', y='prop_negados', kind='line')
4.4 Otimização
A otimização visual é um assunto extenso e muito baseado em tentativa e erro. Afinal, o que queremos aqui é adaptar nosso gráfico para um fim específico, e isso pode variar muito. Nessas situações, o chatGPT e ferramentas similares podem ser muito úteis!
Vamos colocar alguns exemplos de otimização aqui:
Colocar o % nos eixos que são porcentagens
Mudar o título dos eixos
Mudar as cores das barras
Mudar a cor de fundo
Colocar o % nos eixos que são porcentagens
Vamos voltar para o gráfico que vimos anteriormente
sns.catplot(ct_mag, x ='prop', y ='decisao', kind ='bar', hue ='rel_tipo_magistrado')
# função para formatar eixo xdef to_pct(x, pos):returnf'{100*x:.0f}%'sns.catplot(data=ct_mag, x='prop', y='decisao', kind='bar', hue='rel_tipo_magistrado')# gca: get current axisplt.gca().xaxis.set_major_formatter(to_pct)
# Outro jeito, usando um pouco mais de matplotlib. Não dá para usar catplotfig, ax = plt.subplots()sns.barplot(data=ct_mag, x='prop', y='decisao', hue='rel_tipo_magistrado', ax=ax)ax.xaxis.set_major_formatter(plt.FuncFormatter(to_pct))
Veja que precisamos voltar a usar uma função mais ‘baixo nível’, a barplot
# Aumentar a resolução mudando dpi (dots per inch)# obs: afeta todo o documento!plt.rcParams.update({"figure.dpi": 150})fig, ax = plt.subplots()sns.barplot(data=ct_mag, x='prop', y='decisao', hue='rel_tipo_magistrado', ax = ax, palette='mako')ax.xaxis.set_major_formatter(to_pct)ax.set_xlabel('Proporção')ax.set_ylabel('Decisão')ax.legend(title ='Tipo de magistrado')plt.show()
# também é possível mudar a configuração do jupyter%config InlineBackend.figure_format ="svg"# mais informações: https://seaborn.pydata.org/faq.html#why-do-the-plots-look-fuzzy-in-a-jupyter-notebookfig, ax = plt.subplots()sns.barplot(data=ct_mag, x='prop', y='decisao', hue='rel_tipo_magistrado', ax = ax, palette='mako')ax.xaxis.set_major_formatter(to_pct)ax.set_xlabel('Proporção')ax.set_ylabel('Decisão')ax.legend(title ='Tipo de magistrado')plt.show()
# Vamos voltar ao 'normal'%config InlineBackend.figure_format ="png"plt.rcParams.update({"figure.dpi": 100})