O pacote Matplotlib Python é uma ferramenta poderosa para criar gráficos e analisar dados em formato gráfico. Neste tutorial, vamos ver como utilizar esta biblioteca e algumas das caraterísticas que precisa de conhecer.
Instalar o Matplotlib
A biblioteca Matplotlib é instalada como qualquer outro pacote Python
python -m pip install matplotlib
Para manipular os dados, pode utilizar o Numpy e o Panda
python -m pip install numpy pandas
Recuperação de dados a rastrear
É possível recuperar dados de ficheiros CSV com o Pandas
| time | myData |
| 0 | 32.0 |
| 1 | 46.2 |
| 2 | 2490 |
| … | … |
| 10 | -2,45 |
import pandas as pd df = pd.read_csv(filename,sep=";",encoding = "ISO-8859-1",header=1) mydata = df["myData"]
Também é possível processar os dados criados pelo seu programa com o Numpy
import numpy as np
ylist=[]
x = np.linspace(0, 10, 1000)
for i in range(8):
y = np.random.randn(1)*np.sin((i+1)*np.random.randn(1)*x) # + 0.8 * np.random.randn(50)
ylist.append(y)
Vamos utilizar este último método para desenhar curvas
Desenhar uma figura simples
Para traçar uma curva, comece por criar uma janela (figura) e depois crie uma curva (traçado).
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
#plt.close('all') #close all figure
#process data
ylist=[]
x = np.linspace(0, 10, 1000)
for i in range(8):
y = np.random.randn(1)*np.sin((i+1)*np.random.randn(1)*x)
ylist.append(y)
#single plot
fig = plt.figure()
plt.plot(x, y) # plot(y)
#mutliple plots
fig = plt.figure()
for y in ylist:
plt.plot(x, y)
O gráfico é apresentado na figura ativa. Para tornar uma figura ativa, pode atribuir-lhe nomes ou números ou recordar a ordem pela qual foi criada.
fig1 = plt.figure(1)
fig2 = plt.figure(2)
fig3 = plt.figure("myData")
# use fig2
plt.figure(1) # make fig1 active
#use fig1
Números aproximados
Depois de ter feito o que pretendia com a figura, pode fechá-la com o comando plt.close().
plt.close() #close active figure
plt.close(1) # plot first created figure or figure 1
plt.close("myData") #plot figure named myData
plt.close('all') # close all figures
N.B.: plt.close(‘all’) pode ser colocado no início do programa para fechar todas as janelas previamente abertas quando o programa é executado.
Guardar uma figura em formato de imagem
É possível guardar cada imagem traçada utilizando o ícone de guardar na janela. Também pode pedir ao pyplot para guardar a figura em formato PNG ou JPG.
plt.savefig("myImg.jpg",bbox_inches='tight') #png no label
Personalizar a figura
Vimos que podemos atribuir um identificador à figura (plt.figure(“myData”). É possível definir outros parâmetros, nomeadamente
- o tamanho da janela figsize
- a cor de fundo facecor
- especificar um título suptitle
pyplot.figure(num=None, figsize=None, dpi=None, *, facecolor=None, edgecolor=None, frameon=True, FigureClass=<class 'matplotlib.figure.Figure'>, clear=False, **kwargs)
#customize figure
fig = plt.figure("myData",figsize=(12,4),facecolor=(0.5, 0.8, 0.3))
fig.suptitle("myFigure")
plt.plot(x, y)
Personalizar o gráfico
Para completar a personalização da figura, podemos personalizar o gráfico
- o título do gráfico
- etiquetas de eixo
- a legenda e a sua posição
- o extremo dos eixos
#customize plot
fig = plt.figure("myData",figsize=(12,4),facecolor=(1, 1, 1))
plt.title("myData y(x)")
plt.plot(x, y, label="y(x)")
plt.axis([min(x)-1, max(x)+1, min(y)*1.05, max(y)*1.05]);
plt.xlabel("x [s]")
plt.ylabel("y [SI]")
plt.legend(loc='upper left')
Personalizar a curva
Como vimos, quando desenha várias curvas, o Matplotlib seleciona estilos diferentes para cada curva. É possível personalizar as curvas de uma forma específica.
- estilo de linha (ls)
- cor da linha cor
- largura da linha largura da linha (lw)
- marcador de estilo marcador
- markerfacecor (mfc) markeredgecor (mec)
- tamanho do marcador tamanho do marcador (ms)
## customize curve fig = plt.figure() plt.plot(x, y, "ko--") plt.axis([4, 4.5, min(y)*1.05, max(y)*1.05]); #plt.plot(x, y, color="k", linestyle="--", linewidth=1, marker= "o") #equivalent
#customize marker fig = plt.figure() plt.plot(x, y, marker = 'o', ms = 5, mfc = 'r', mec = 'k') plt.axis([4, 4.5, min(y)*1.05, max(y)*1.05]);
Criar uma função para desenhar curvas
Como há um grande número de parâmetros a definir para a criação de gráficos com o Matplotlib, aconselho-o vivamente a criar uma função de criação de gráficos que simplifique a sua vida e que possa ser adaptada conforme necessário.
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
plt.close("all")
ylist=[]
ylbl = []
x = np.linspace(0, 10, 1000)
for i in range(8):
y = np.random.choice([-1,1])*(i+1)*np.sin((i+1)*x)
ylist.append(y)
ylbl.append('y{}(x)'.format(i))
##styles options
lstyles= ['-', '--', '-.', ':', 'None', ' ', '', 'solid', 'dashed', 'dashdot', 'dotted']
markers = [None,'o','*','.',',','x','X','+','P','s','D','d','p','H','h','v','^','<','>','1','2','3','4','|','_']
def tracefig(x,y,lbl,ls=None,mrkr=None,title=None,xlbl=None,ylbl=None,size=(12,4),zoomx=None,gridon=False):
fig = plt.figure(figsize=size,facecolor=(1, 1, 1))
if title is not None:
title = "tracefig - {}".format(title)
plt.title(title)
if type(y) is not list:
if ls is None:
ls=np.random.choice(lstyles)
if mrkr is None:
mrkr=np.random.choice(markers)
plt.plot(x, y, linestyle=ls, marker = mrkr, label=lbl)
else:
for i,y in enumerate(ylist):
if ls is None:
ls=np.random.choice(lstyles)
if mrkr is None:
mrkr=np.random.choice(markers)
plt.plot(x, y, linestyle=ls, marker = mrkr, label=lbl[i])
plt.xlabel(xlbl)
plt.ylabel(ylbl)
plt.legend(loc='upper left')
if zoomx is None:
plt.axis([min(x), max(x), np.min(ylist)*1.2, np.max(ylist)*1.2]);
else:
plt.axis([zoomx[0], zoomx[1], np.min(ylist)*1.2, np.max(ylist)*1.2]);
if gridon:
plt.grid() #diplay grid
return fig
fig = tracefig(x,y,"y(x)",ls="-",mrkr="o",title="Single plot",xlbl="x [s]",ylbl="y [SI]",size=(12,4),zoomx=[0,2])
fig = tracefig(x,ylist,ylbl,ls="-",mrkr=None,title="Multi plots",xlbl="x [s]",ylbl="y [SI]",size=(12,4),zoomx=[0,2], gridon=True)
Com estes conhecimentos, pode desenhar e analisar todos os tipos de curvas utilizando Matplotlib e Python.
Visualizar nuvens de pontos
Para a análise de dados, também é possível apresentar gráficos de dispersão. Neste exemplo, corimos os pontos em função de uma terceira variável
import matplotlib.pyplot as plt
import numpy as np
plt.close("all")
x = np.random.randn(50)
y = np.random.randn(50)
z = np.random.randint(1,100,50) #np.random.randn(50)
value=(z>50)
colors = np.where( value==True , "red", "#3498db")
fig = plt.figure()
plt.scatter(x,y,marker='s',color=colors)
plt.show()
Desenhar histogramas
Para cada tipo de dados existe uma representação adequada. Em alguns casos, um histograma é mais significativo.
import matplotlib.pyplot as plt
import numpy as np
plt.close("all")
nb = 10
x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
fig = plt.figure()
plt.hist(x_multi, nb, histtype='bar', label=['d1','d2','d3'])
plt.legend(prop={'size': 10})
plt.title('Histogram')
plt.show()
Desenhar gráficos de pizza
import matplotlib.pyplot as plt labels = 'Insurance', 'Workshop', 'Salary', 'Bank' sizes = [15, 30, 45, 10] explode = (0, 0.05, 0, 0) fig, ax = plt.subplots() ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',colors=['olivedrab', 'rosybrown', 'gray', 'saddlebrown'],startangle=80)
Desenhar contornos
Os contornos são úteis para traçar dados 3D, tais como gradientes, em 2D.
import numpy as np import matplotlib.pyplot as plt def g(x, obs = [[-2,0],[8,-5]], param = [[1000,20, 60],[500,10, 30]]): res = 200 for i in range(0,len(obs)): alpha_obstacle, a_obstacle,b_obstacle = param[i] x_obstacle , y_obstacle = obs[i] res += -alpha_obstacle * np.exp(-((x[0] - x_obstacle)**2 / a_obstacle + (x[1] - y_obstacle)**2 / b_obstacle)) return res x = np.linspace(-10, 10, 200) y = np.linspace(-10, 10, 200) X = np.meshgrid(x, y) Z = g(X) CS = plt.contour(X[0], X[1], Z) #, colors='black') plt.clabel(CS, fontsize=9, inline=True) plt.show()
Criar gráficos com Matplotlib
Para uma visão mais abrangente dos dados, uma técnica importante é poder traçar vários gráficos na mesma figura.
Utilização de subparcelas
É possível dividir uma figura em linhas e colunas para organizar as curvas de forma mais clara e ligar os eixos mais facilmente.
fig = plt.figure() ax_list = fig.subplots(row, col, sharex=True, sharey=True)
import matplotlib.pyplot as plt
import numpy as np
plt.close("all")
ylist=[]
ylbl = []
x = np.linspace(0, 10, 1000)
for i in range(8):
y = np.random.choice([-1,1])*(i+1)*np.sin((i+1)*x)
ylist.append(y)
ylbl.append('y{}(x)'.format(i))
fig2 = plt.figure(figsize=(8, 6))
fig2.suptitle("my Plots")
#devide figure in 3 rows and 2 columns with shared axis
(row1col1, row1col2),(row2col1, row2col2),(row3col1, row3col2) = fig2.subplots(3, 2,sharex=True,sharey=True)
ax = row1col1
ax.plot(x, ylist[0], label="y1(x)")
ax.set_title('Y(X)')
ax = row1col2
ax.plot(x, ylist[1], label="y1(x)")
ax = row2col1
ax.plot(x, ylist[2], label="y2(x)")
ax = row2col2
ax.plot(x, ylist[3], label="y3(x)")
ax = row3col1
ax.plot(x, ylist[4], label="y4(x)")
ax = row3col2
ax.plot(x, ylist[5], label="y5(x)")
Utilização de subfiguras
Para layouts mais complexos, é possível utilizar a subfigura
fig = plt.figure(figsize=(10, 8))
(row1fig, row2fig) = fig.subfigures(2, 1, height_ratios=[1, 2])
row1fig.suptitle("Subfigure")
(fig_row2left, fig_row2right) = row2fig.subfigures(1, 2)
row1_ax = row1fig.add_subplot()
row2l_axs = fig_row2left.subplots(2,1)
row2r_ax = fig_row2right.add_subplot()
ax = row1_ax
ax.plot(x, ylist[0])
ax = row2l_axs[0]
ax.plot(x, ylist[2],'ro-')
ax = row2l_axs[1]
ax.plot(x, ylist[3],'k.-')
ax = row2r_ax
ax.plot(ylist[4], ylist[5],'g-')
Utilização do GridSpec
O GridSpec torna possível desenhar rapidamente layouts complexos. Em vez de dividir as áreas uma após a outra, vamos definir uma grelha que será preenchida à medida que avançamos com sub-gráficos.
fig = plt.figure(figsize=(10, 8))
fig.suptitle("GridSpec")
gs = plt.GridSpec(3, 3)
gs.update(wspace=0.4, hspace=0.6)
col1fig0 = fig.add_subplot(gs[0, :2])
col1fig1 = fig.add_subplot(gs[1, :2],sharex=col1fig0)
col1fig2 = fig.add_subplot(gs[2, :2],sharex=col1fig0)
col2fig0 = fig.add_subplot(gs[:1, 2])
col2fig1 = fig.add_subplot(gs[1:, 2])
ax=col1fig0
ax.plot(x, ylist[1], label="y1(x)")
ax=col1fig1
ax.plot(x, ylist[2], 'kx-',label="y2(x)")
ax=col1fig2
ax.plot(x, ylist[3], 'ro:', label="y3(x)")
ax=col2fig0
ax.plot(ylist[4], ylist[5], 'g-',label="y5(y4)")
ax=col2fig1
ax.plot(ylist[6],x,'s', label="y6(x)")
fig.legend(loc='upper left')
N.B.: Pode combinar subfigura, subparcela e gridspec e encaixá-los como quiser para criar os gráficos mais bonitos.
Adicionar um cursor aos seus gráficos
Para facilitar a leitura, pode adicionar um cursor para visualizar certos pormenores com mais precisão. Este cursor pode ser partilhado entre várias curvas. Por exemplo, podemos adicionar um cursor às três curvas à esquerda da figura anterior e definir os seguintes parâmetros
- ls estilo de linha
- lw largura da linha
- cor
- horizOn linha horizontal
- verdeNa linha vertical
from matplotlib.widgets import MultiCursor figlist = (col1fig0,col1fig1,col1fig2) cursor = MultiCursor(fig.canvas, figlist, color='r',lw=0.5, ls='--', horizOn=True,vertOn=True)
Detetar eventos do rato
Para além de desenhar e animar curvas, também pode utilizar o rato para interagir com o gráfico.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backend_bases import MouseButton
def on_click(event):
if event.button is MouseButton.LEFT:
print("Click detected at X,Y: {}".format([event.xdata, event.ydata]))
fig = plt.figure()
plt.plot([0,1],[0,2])
plt.connect('button_press_event', on_click)
plt.show()
Criar uma animação com Matplotlib
É possível criar gráficos animados e guardá-los em vários formatos utilizando a ferramenta matplotlib.animation. Para tal, é necessário traçar o gráfico quadro a quadro numa função update(frame), que devolve o objeto que contém o gráfico (neste caso, a curva).
import math
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
#create data
#process data
x = np.linspace(0, 10, 100)
y = np.sin(2*x)
# plot first point
fig = plt.figure()
curve = plt.plot(x[0], y[0])
plt.axis([0, 10, -1.2, 1.2])
def update(frame):
# update data
xi = x[:frame]
yi = y[:frame]
# update plot
curve[0].set_xdata(xi)
curve[0].set_ydata(yi)
return (curve)
#display animation
ani = animation.FuncAnimation(fig=fig, func=update, frames=100, interval=30)
plt.show()
#save animation as gif
ani.save(filename="./tmp/sinewave.gif", writer="pillow")
Existem diferentes formas de criar animações, consoante os tipos de dados. Também pode guardar as animações em diferentes formatos, consoante a sua utilização. Não hesite em consultar a documentação sobre animações.
Aplicações
- Visualizar dados de um sensor Lidar
- Apresentar imagens de uma câmara
- Visualizar os seus algoritmos e dados
