Skip to main content

Visualização de Dados com Matplotlib e Seaborn 📊

Uma das habilidades mais importantes num cientista ou analista de dados é a habilidade de criar visualizações representativas, bonitas, e que contem uma história clara sobre os dados as quais representam, independente de quem as veja.

Nesta seção, adentraremos no tópico de visualização de dados com Python usando os módulos Matplotlib e Seaborn.

Para os exemplos desse artigo, iremos utilizar dois datasets obtidos no Kaggle:

  1. Airbnb Open Data - Tokyo, Japan (2023)

  2. Huge Stock Market Dataset

Ambos os projetos estarão disponíveis no GitHub, e explicados em maiores detalhes na aba de projetos.

Visualizações Simples com pandas

Muitas vezes, numa análise exploratória, queremos verificar a distribuição de uma coluna rapidamente, ou observar um trecho de uma série temporal com facilidade. Para isso, podemos utilizar a funcionalidade integrada à pandas para plotagens.

Essa funcionalidade foi construída com a própria Matplotlib, e permite a criação rápida de gráficos simples.

Plotagem com Pandas
PositivosNegativos
Plotagem facilitadaBaixa Customização

Line Plot

Via de regra, podemos fazer:

Line Plot
df.plot(x='Column1', y='Column2', title='Title', kind='line')

Vamos analisar como exemplo os valores de abertura, em dólares, da ação do banco internacional JP Morgan Chase, de 2016 até 2017.

JP Morgan Chase (JPM-A) [Open/Valor de Abertura x Tempo]
#-Podemos plotar diretamente do DF, sem especificar o eixo X, que é o índice (index) por padrão
#-Caso queira/precise, basta especificar o eixo X com x = "..."
df_jpm.plot(y='Open', title='JPM Stock Price', kind='line', figsize=(12, 6))

Line-Plot-1

Area Plot

Podemos utilizar essa plotagem para visualizar as Series do DF como áreas preenchidas:

Area Plot
df.plot(kind='area')

Replicando isso no nosso df_jpm, obtemos:

JP Morgan Chase (JPM-A) [Open+Close+High+Low x Tempo]
#-Selecionando somente algumas colunas do DF
values = df_jpm[['Open', 'High', 'Low', 'Close']]
#-Utilizando os parâmetros adicionais stacked e ylim
#-1. stacked:bool - se as Series devem se acumular uma em topo da outra
#-2. ylim:list/tuple - onde o eixo y deve iniciar e terminar
values.plot(kind='area', stacked=False, figsize=(12, 6), ylim=[23.8,27])

Area-Plot-1

Histogram

Para visualizar a distribuição da frequência dos valores numéricos numa coluna, podemos utilizar o histograma:

Histogram
df['column1'].plot(kind='hist', bins=20)

Vamos observar a distribuição da coluna de aberturas:

JP Morgan Chase (JPM-A) [Open]
df_jpm['Open'].plot(kind='hist', bins=30, figsize=(12, 6))

Hist-1

Box Plot

Podemos observar a distribuição de uma coluna, em conjunto com métricas estatísticas e outliers.

Boxplot
df.plot(kind='box')

Observe essa visualização aplicada no nosso sub-DF values:

JP Morgan Chase (JPM-A) [Open+Close+High+Low]
values.plot(kind='box', figsize=(12, 6))

Box-1

Como interpretar um Box Plot?

Boxplot-Inference

  1. Outliers: pontos extremos

  2. Máximo: valor máximo calculado sem outliers

  3. Mínimo: valor mínimo calculado sem outliers

  4. First Quartile (Primeiro Quartil): 25% dos registros são abaixo desse valor (localizado nos 1/4)

  5. Median (Mediana): 50% dos registros são abaixo desse valor (valor intermediário)

  6. Third Quartile (Terceiro Quartil): 75% dos registros são abaixo desse valor (localizado nos 3/4)

  7. IQR (Inter Quartile Range): Intervalo entre o primeiro e o terceiro quartil (25%-75%)

Scatter Plot

Essa visualização é composta de duas variáveis numéricas (de preferência, contínuas). É uma visualização exemplar em observação de correlações entre as variáveis.

Scatter
df.plot(x="Column1", y="Column2", kind='scatter')

Vejamos a relação entre o volume de ações negociado e o valor de fechamento:

JP Morgan Chase (JPM-A) [Close x Volume]
df_jpm.plot(x='Close', y='Volume', kind='scatter', figsize=(12, 6))

Scatter-1

Pie Chart

O clássico gráfico de pizza, representa a proporção de valores categóricos numa coluna.

Pie Chart
df['column1'].plot(kind='pie', autopct='%1.1f%%')

Como no dataset de mercado financeiro não temos variáveis categóricas, podemos fazer:

JP Morgan Chase (JPM-A) [Growth]
#-Podemos criar uma nova coluna categórica que indica se o registro atual teve abertura maior 
#-que o anterior, indicando crescimento.
df_jpm['Growth'] = df_jpm['Open'] > df_jpm['Open'].shift(1)
df_jpm['Growth'].value_counts().plot(kind='pie', figsize=(6, 6), autopct='%1.1f%%')

Pie-1

Bar Chart

O gráfico de barras, amplamente utilizado para representar a contagem de uma coluna categórica ou uma relação entre uma variável categórica e uma numérica.

Bar Chart
df.plot(kind='bar')

Como no dataset de mercado financeiro não temos variáveis categóricas, podemos fazer:

JP Morgan Chase (JPM-A) [Growth]
df_jpm['Growth'].value_counts().plot(kind='bar', figsize=(12, 6))

Pie-1

Visualizações completas com Matplotlib

A biblioteca mais famosa e utilizada para visualizações, Matplotlib, permite alto nível de customização e oferta muitos tipos de visualizações diferentes.

Arquitetura de Matplotlib

Esse módulo é composto de 3 camadas as quais podemos interagir em situações diferentes:

  1. Backend Layer (FigureCanvas, Renderer, Event)
  2. Artist Layer (Artist)
  3. Scripting Layer (pyplot, a mais utilizada no dia a dia)

Observe a anatomia de uma plotagem com Matplotlib:

Anatomy

Observando acima, podemos perceber o nível de customização que essa biblioteca nos permite.

Plotagem com Matplotlib
PositivosNegativos
Diversos tipos de plotagens disponíveisMenor facilidade de manipulação
Alto poder de customizaçãoMaior tempo e energia customizando

Para as próximas visualizações, com exceção do Line Plot, usaremos outro conjunto de dados, especificado no início do artigo, de listagens de propriedades em Tokyo, Japão no Airbnb em 2023.

Dica de Estilização

É possível selecionar um estilo para todos as suas visualizações. Para escolher o estilo, clique aqui e procure um que te agrada..

Depois, execute o comando:

#-Aqui, estamos utilizando 'ggplot', por exemplo
import matplotlib
mpl.style.use('ggplot')

Line Plot

Um gráfico de linha pode ser criado da seguinte maneira:

Line Chart MPL
plt.plot(x, y, color='color', linewidth=1)

plt.title('Title')
plt.xlabel('X Label')
plt.ylabel('Y Label')

plt.show()

Para este exemplo, repetiremos o exemplo anterior de Line Chart do dataset da bolsa de valores americana.

JP Morgan Chase (JPM-A) [Open x Time]
#-Definindo o tam. da figura
plt.figure(figsize=(14, 6))

#-Plotando x,y
plt.plot(df_jpm.index,
df_jpm['Open'],
color='green',
linewidth=2,
linestyle='-')

#-Customizando o título e as legendas
plt.title('JPM Stock Price Open from 2016 to 2017')
plt.xlabel('Date')
plt.ylabel('Price at Open')

#-Colocando os limites do eixo X 1 semana antes e depois do primeiro e último registro
plt.xlim(df_jpm.index.min() - pd.Timedelta(days=7), df_jpm.index.max() + pd.Timedelta(days=7))

plt.show()

Line-Plot-2

Com a Matplotlib, podemos até criar uma animação:

gif-stock

Código da Animação
    import matplotlib.animation as animation

# Create a figure and axis
fig, ax = plt.subplots(figsize=(14, 6))

# Initialize an empty line object
line, = ax.plot([], [], lw=2)

# Set the x and y limits of the plot
ax.set_xlim(df_jpm.index.min(), df_jpm.index.max())
ax.set_ylim(df_jpm['Open'].min()-1, df_jpm['Open'].max()+1)

# Define the update function for the animation
def update(frame):
# Get the data for the current frame
data = df_jpm['Open'][:frame+1]
x = df_jpm.index[:frame+1]

# Update the line data
line.set_data(x, data)

return line,

# Create the animation
ani = animation.FuncAnimation(fig, update, frames=len(df_jpm), interval=20, blit=True)

ani.save('jpm_stock_price.gif', writer='pillow')

Area Plot

Um gráfico de área pode ser criado da seguinte maneira:

Area Chart MPL
plt.fill_between(x, y1, y2, color=['color1','color2'], alpha=0.5)

plt.title('Title')
plt.xlabel('X Label')
plt.ylabel('Y Label')

plt.show()

Para este exemplo, repetiremos também o exemplo anterior de Area Chart do dataset da bolsa de valores americana.

JP Morgan Chase (JPM-A) [Open x Time]
#-Aqui, estamos plotando cada uma das colunas individualmente

plt.figure(figsize=(14, 6))

plt.fill_between(x=df_jpm.index,
y1=df_jpm['Open'],
color=['blue'],
alpha=0.3)

plt.fill_between(x=df_jpm.index,
y1=df_jpm['Close'],
color=['yellow'],
alpha=0.3)

plt.fill_between(x=df_jpm.index,
y1=df_jpm['High'],
color=['green'],
alpha=0.3)

plt.fill_between(x=df_jpm.index,
y1=df_jpm['Low'],
color=['red'],
alpha=0.3)

#-Customizando o título e as legendas
plt.title('JPM Stock Price Open, Close, High and Low from 2016 to 2017')
plt.xlabel('Date')
plt.ylabel('Price at Open')

#-Colocando os limites do eixo X 1 semana antes e depois do primeiro e último registro
plt.xlim(df_jpm.index.min() - pd.Timedelta(days=7), df_jpm.index.max() + pd.Timedelta(days=7))

#-Colocando os limites de y num quadro mais focado
plt.ylim(23.7, df_jpm['High'].max()*1.005)

plt.legend(['Open', 'Close', 'High', 'Low'])

plt.show()

Area-Plot-2

Não tem muita diferença do gráfico de área anterior... porém, agora podemos comparar diferentes DFs numa mesma visualização:

JP Morgan Chase (JPM-A) x Bank of America (BAC-A)
plt.figure(figsize=(14, 6))

#-Plotando os dados de JPM
plt.fill_between(x=df_jpm.index,
y1=df_jpm['Open'],
color=['blue'],
alpha=0.4)

#-Plotando os dados de BAC
plt.fill_between(x=df_bac.index,
y1=df_bac['Open'],
color=['green'],
alpha=0.4)


#-Customizando o título e as legendas
plt.title('JPM x Bank of America Stock Price from 2016 to 2017')
plt.xlabel('Date')
plt.ylabel('Price at Open')

#-Colocar os limites do eixo X 1 semana antes e depois do primeiro e último registro
plt.xlim(df_jpm.index.min() - pd.Timedelta(days=7), df_jpm.index.max() + pd.Timedelta(days=7))

#-Colocando os limites de y num quadro mais focado
plt.ylim(23.7, df_bac['High'].max()*1.005)

#-Legendando
plt.legend(['JPM', 'BAC'])

#-Adicionando uma linha para uma anotação
plt.annotate('',
xy=(df_jpm.index[135], 24.25),
xytext=(df_jpm.index[89], 25),
xycoords='data',
arrowprops=dict(color='red', arrowstyle='->', lw=2, connectionstyle='arc3'))

#-Adicionando o texto da anotação
plt.annotate('2016 U.S. Elections',
xy=(df_jpm.index[135], 24.4),
rotation=-38,
ha='right',)

plt.show()

Area-Plot-3

Visualizações avançadas com Seaborn