Uma tarefa muito comum para os cientistas de dados é plotar gráficos em Python. Embora seja simples, essa atividade traz muitos insights sobre os dados e pode, até mesmo, revelar padrões que estão ocultos.
Existem diversas bibliotecas destinadas a visualização de dados: matplotlib, seaborn, pyplot, etc. O nosso objetivo aqui é ir além do simples .plot()
e conseguir colocar os rótulos de dados de cada categoria.
Neste artigo, vamos misturar a seaborn com a matplotlib para mostrar que é possível usar várias bibliotecas ao mesmo tempo.
Se lembrarmos do Excel, essa tarefa de rotulação é muito simples. Já no Python, precisamos de um entendimento maior de como funcionam os objetos das bibliotecas.
Sem mais delongas, bora para o código! 🐍
O que você vai aprender por aqui:
- Criar rótulos em gráficos de barras.
- A estrutura de objetos do matplotlib.
- Customização de gráficos.
Criando uma base de dados
Antes de tudo, precisamos criar uma base de dados qualquer. O que importa aqui é como vamos fazer os gráficos.
Neste caso, iremos representar um dataset que simula a quantidade vendida de frutas por uma empresa em um determinado período.
#criando o DataFrame
df = pd.DataFrame({'Frutas':['Laranja','Maçã','Melão','Kiwi','Banana'], # Nome das frutas
'Quantidade':[200,500,1200,600,800]}) # Quantidade vendida de cada fruta
#ajustando a ordem do DataFrame
df.sort_values(by='Quantidade', # ordenar pela quantidade
ascending=False, # colocar na ordem contrária a ascendente (portanto, descendente <- maior para o menor)
inplace=True, # atualizar o DataFrame com as mudanças
ignore_index=True) #ignorar índice anterior
A forma mais comum de se plotar qualquer gráfico
Vamos criar um gráfico de barras na vertical utilizando o searborn. As frutas ficarão no eixo x (horizontal), já a quantidade no eixo y (vertical).
sns.barplot(x='Frutas',y='Quantidade',data=df); #plotando o gráfico. O ponto-e-vírgula (;) é para não retornar o texto do objeto
Até aqui, nada de mais.
Adicionando valor ao seu gráfico
E se alguém do departamento de Kiwis lhe perguntasse: Ok, estou entendendo completamente este gráfico. Porém, exatamente quantos Kiwis foram vendidos neste período? Sem uma resposta clara, você seria obrigado a voltar ao seu banco de dados e dar um retorno no dia seguinte.
Por causa deste tipo de problema, precisamos aprender a colocar rótulos nos gráficos. Entretanto, antes disso, vamos entender como funciona a criação de gráficos (e outros objetos) no matplotlib.
A imagem abaixo representa o que acontece de maneira geral dentro desta biblioteca.
Existem três objetos muito importantes: Figure, Axes e o gráfico que você quer criar. Pela imagem, é possível perceber que existe uma hierarquia entre eles.
O Figure é considerado o objeto top level que contém todos os elementos que serão plotados. Ele pode ter vários objetos do tipo Axes.
Já o Axes é o pano de fundo para o seu gráfico.
E, por fim, o último objeto é o gráfico (em si) que queremos criar.
Show! Com essas ideias em mente, vamos criar um Figure com apenas um Axes no matplotlib.
Para colocar o gráfico especificamente dentro do Axes criado, podemos adicionar o parâmetro (ax=ax) do searborn.
#criando a Figure e o Axes no matplotlib
fig, ax = plt.subplots(figsize=(8,6)) # figsize posso escolher o tamanho do meu figure
#criando novamente o gráfico
sns.barplot(x='Frutas',y='Quantidade',data=df,ax=ax) #criar o gráfico para colocar dentro do Axes
#plotando o gráfico
plt.tight_layout(); # <- plotando a Figure
Agora que entendemos os conceitos de objetos, podemos ir mais a fundo e adicionar títulos, retirar este retângulo preto (frame) que encobre nosso gráfico e muito mais! Acompanhe cada detalhe no código abaixo.
#criando a fig e o ax no matplotlib
fig, ax = plt.subplots(figsize=(8,6))
#criando novamente o gráfico
sns.barplot(x='Frutas', # colocando as categorias no eixo x
y='Quantidade', # colocando os valores no eixo y
data = df, # selecionando a base de dados
ax=ax) # definindo o Axes criado
#modificação do fundo
ax.set_frame_on(False) # retirando o Frame (retângulo que encobre os gráficos)
#adicionando um título
ax.set_title('Quantidade de Frutas Vendidas', # texto do título
loc='left', # posicionamento do título no Axes
pad=30, # Distanciamento do título com outros objetos
fontdict={'fontsize':20}, # Tamanho da fonte utilizado
color='#3f3f4e') # cor da fonte em hexadecimal
#retirando o eixo y
ax.get_yaxis().set_visible(False) # retirando o eixo Y
#retirando os ticks do eixo x
ax.tick_params(axis='x', # escolhendo os ticks do eixo x
length=0, # colocamos os ticks de tamanho zero, compare com os desenhos de cima
labelsize=12, # tamanho da fonte para os eixos
colors='dimgrey') # cor da fonte para o eixo x
#ajustando o título Frutas do eixo
ax.set_xlabel('Frutas', # título que queremos colocar na parte horizontal (em baixo)
labelpad=10, # distanciamento deste título com outros objetos
fontdict={'fontsize':14}, # tamanho da fonte utilizado
color='#4c4c4c') # cor da fonte em hexadecimal
#plotando o gráfico
plt.tight_layout();
Certo, mas e os rótulos?
Nós precisamos colocar um rótulo em cima de cada retângulo. Estas regiões do Axes com características específicas são chamadas, no matplotlib, de patch. Existem vários tipos de patches: linhas, elipses, retângulos, etc.
Vamos acessar os patches — regiões com características singulares — de nosso Axes por meio do método ax.patches()
, e ver o que retorna:
<matplotlib.patches.Rectangle at 0x7fbf36afb450>,
<matplotlib.patches.Rectangle at 0x7fbf36afb750>,
<matplotlib.patches.Rectangle at 0x7fbf36afbc10>,
<matplotlib.patches.Rectangle at 0x7fbf36afbfd0>,
<matplotlib.patches.Rectangle at 0x7fbf36b04550>
Bingo! Ele retornou 5 linhas, que representam cada um de nossos retângulos. Nós precisamos acessar cada um destes retângulos para entender quais as medidas e descobrir qual a localização exata deles no Axes.
Se dermos uma olhada na documentação específica do Rectangle, encontraremos alguns métodos interessantes que podem nos ajudar:
- ax.patches[0].get_height() <- retorna a altura do retângulo
- ax.patches[0].get_x() <- retorna a coordenada x inicial (à esquerda) do retângulo
- ax.patches[0].get_width() <- retorna a largura do retângulo
Obs.: Utilizando o índice [0], estamos acessando as propriedades do primeiro retângulo.
Agora vamos retornar ao nosso código e inserir esses métodos!
#colocando os rótulos
for retangulo in ax.patches: # for para cada retângulo
# vamos inserir um texto no Axes
ax.text(retangulo.get_x(), # posição x
retangulo.get_height(), # posição y
'texto') # texto que queremos colocar
Opa, já conseguimos enxergar algumas mudanças. O texto que colocamos ficou bem em cima de cada retângulo. Além disso, este texto ficou muito para a esquerda, pois escolhemos o ponto inicial de x com o retangulo.get_x()
, ou seja, o ponto mais à esquerda de cada retângulo.
Vamos fazer alguns ajustes para colocar cada texto de uma forma que faça mais sentido visualmente!
#colocando os rótulos
for retangulo in ax.patches:
ax.text(retangulo.get_x() + patch.get_width() / 2, # adicionando a metade da largura para ficar no centro
retangulo.get_height() + 22, # adicionando um valor a mais na altura
'texto',
ha = 'center')
Quarto gráfico plotado após os conceitos de objetos
Conseguimos! O texto ficou na parte central do nosso retângulo. Além disso, adicionamos 22 unidades para gerar um espaço em branco entre cada rótulo e retângulo. Este número varia de gráfico para gráfico, e é uma boa você experimentar diferentes valores.
Agora é hora de colocar o texto correto: a quantidade de frutas. Para isso, vale lembrar que o método retangulo.get_height()
retorna o valor da altura de cada retângulo.
As strings em Python possuem o método .format()
. Com este método, conseguimos adicionar qualquer tipo de valor! Para isso, basta colocar "{}"
no local que queremos inserir o texto e passar a variável que queremos como parâmetro do .format()
Exemplo: "{}".format(sua_variável)
Dê uma olhada no código abaixo e veja como foi feito para este caso.
#colocando os rótulos
for retangulo in ax.patches:
ax.text(retangulo.get_x() + retangulo.get_width() / 2,
retangulo.get_height() + 22,
'{:,}'.format(int(retangulo.get_height())).replace(',','.'), # adicionando o texto da altura
ha = 'center')
s de objetos
Sim, há bastante coisa na parte do texto. Porém, tudo aquilo é só firula para ficar mais visual… com separador de milhar, etc.
Um ponto importante aqui é que você pode adicionar símbolos ou outros textos de sua preferência. Você faria isso utilizando:
"R${}".format(sua_variavel_em_dinheiro) <- para exibir moedas
"{} milhões".format(sua_variável_em_milhões) <- para exibir milhões
Aplicando tudo o que foi visto e colocando um pouquinho de perfumaria
Vamos voltar ao nosso problema inicial.
Alguém do departamento de Kiwis queria saber a quantidade exata de kiwis vendidos. Poderíamos mostrar, como resposta, este gráfico, que traz os rótulos e dá uma evidencia maior à quantidade vendida de Kiwis.
Cumprimos nosso objetivo! 👊
Entendemos como colocar rótulos nos gráficos, a estrutura de objetos do matplotlib e que é possível customizar e ir além do simples .plot().
Se estiver interessado em como fazer o gráfico acima, eu coloquei o código aqui embaixo. Ademais, se quiser trocar uma ideia sobre Data Science no LinkedIn do Thales Ferraz, é só chamar!
#criando a fig e o ax no matplotlib
fig, ax = plt.subplots(figsize=(8,6))
#criando novamente o gráfico
sns.barplot(x='Frutas',y='Quantidade',data=df,ax=ax,palette=['grey','grey','#281e5d','grey','grey'])
#modificação do fundo
ax.set_frame_on(False)
#adicionando um título
ax.set_title('Quantidade de Frutas Vendidas',loc='left',pad=30,fontdict={'fontsize':20},color='#3f3f4e')
#retirando o eixo y
ax.get_yaxis().set_visible(False)
#retirnado os ticks do eixo x
ax.tick_params(axis='x',length=0,labelsize=12,colors='dimgrey')
#ajustando o título Frutas do eixo
ax.set_xlabel('Frutas',labelpad=10,fontdict={'fontsize':14},color='#4c4c4c')
#colocando os rótulos
for retangulo in ax.patches:
ax.text(retangulo.get_x() + retangulo.get_width() / 2,
retangulo.get_height() + 22,
'{:,}'.format(int(retangulo.get_height())).replace(',','.'),
ha = 'center',
fontsize=18,color='grey')
#plotando o gráfico
plt.tight_layout();
Perfeito… Obrigada
Muito obrigado pelo comentário!