El paquete Matplotlib de Python es una potente herramienta para crear gráficos y analizar datos de forma gráfica. En este tutorial veremos cómo utilizar esta biblioteca y algunas de las funciones que debes conocer.
Instalación de Matplotlib
La biblioteca Matplotlib se instala como cualquier otro paquete de Python
python -m pip install matplotlib
Para manipular los datos, puede utilizar Numpy y Panda
python -m pip install numpy pandas
Recuperación de los datos a rastrear
Es posible recuperar datos de archivos CSV con 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"]
También es posible procesar los datos creados por tu programa con 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 a utilizar este último método para dibujar curvas
Dibujar una figura sencilla
Para trazar una curva, cree primero una ventana (figura) y, a continuación, una curva (trazado).
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)
Para que una figura esté activa, puede darles nombres o números o recordar el orden de creación.
fig1 = plt.figure(1)
fig2 = plt.figure(2)
fig3 = plt.figure("myData")
# use fig2
plt.figure(1) # make fig1 active
#use fig1
Cerrar cifras
Una vez que haya hecho lo que quería con la figura, puede cerrarla con el 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”) puede colocarse al inicio del programa para cerrar todas las ventanas abiertas previamente al ejecutar el programa.
Guardar una figura en formato de imagen
Es posible guardar cada imagen trazada utilizando el icono de guardar en la ventana. También puede pedir a pyplot que guarde la figura en formato PNG o JPG.
plt.savefig("myImg.jpg",bbox_inches='tight') #png no label
Personalizar la figura
Vimos que podíamos dar un identificador a la figura (plt.figure(«misDatos»). Es posible definir otros parámetros, en particular
- el tamaño de la ventana figsize
- el color de fondo facecolor
- especificar un 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 el gráfico
Para completar la personalización de la figura, podemos personalizar el gráfico
- el título del gráfico
- etiquetas de eje
- la leyenda y su posición
- el extremo de los ejes
#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 la curva
Como hemos visto, cuando se dibujan varias curvas, Matplotlib selecciona diferentes estilos para cada curva. Es posible personalizar las curvas de forma específica.
- estilo de línea (ls)
- línea color color
- ancho de línea ancho de línea (lw)
- marcador estilo marcador
- markerfacecolor (mfc) markeredgecolor (mec)
- tamaño del marcador markersize (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]);
Crear una función para dibujar curvas
Como hay un gran número de parámetros a definir para trazar con Matplotlib, te aconsejo encarecidamente que crees una función de trazado que te simplifique la vida y que puedas adaptar según necesites.
# -*- 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)
Con estos conocimientos, podrás trazar y analizar todo tipo de curvas utilizando Matplotlib y Python.
Visualización de nubes de puntos
Para el análisis de datos, también es posible visualizar gráficos de dispersión. En este ejemplo, coloreamos los puntos en función de una tercera variable
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()
Dibujar histogramas
Para cada tipo de datos existe una representación adecuada. En algunos casos, un histograma es más 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()
Dibujar gráficos circulares
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)
Dibujar contornos
Los contornos son útiles para trazar datos 3D, como gradientes, en 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()
Creación de gráficos con Matplotlib
Para obtener una visión más completa de los datos, una técnica importante es poder trazar varios gráficos en la misma figura.
Uso de subtramas
Es posible dividir una figura en filas y columnas para organizar las curvas con mayor claridad y enlazar los ejes más fácilmente.
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)")
Utilizar subfiguras
Para disposiciones más complejas, puede utilizar la 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-')
Uso de GridSpec
GridSpec permite dibujar rápidamente diseños complejos. En lugar de dividir las áreas una tras otra, definiremos una cuadrícula que iremos rellenando con subgrá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.: Puedes combinar subfigure, subplot y gridspec y anidarlos como quieras para crear tus gráficos más bonitos.
Añade un cursor a tus gráficos
Para facilitar la lectura, puede añadir un cursor para ver ciertos detalles con mayor precisión. Este cursor puede compartirse entre varias curvas. Por ejemplo, podemos añadir un cursor a las tres curvas de la izquierda de la figura anterior y definir estos parámetros
- ls estilo de línea
- lw ancho de línea
- color
- horizOn línea horizontal
- verdeEn línea 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)
Detección de eventos de ratón
Además de dibujar y animar curvas, también puedes utilizar el ratón para interactuar con el 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()
Crear una animación con Matplotlib
Puedes crear gráficas animadas y guardarlas en varios formatos utilizando la herramienta matplotlib.animation. Para ello, es necesario trazar el gráfico fotograma a fotograma en una función update(frame), que devuelve el objeto que contiene el gráfico (en este caso 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")
Existen diferentes formas de crear animaciones en función de sus tipos de datos. También puede guardar las animaciones en diferentes formatos dependiendo de su uso. No dude en consultar la documentación sobre animaciones.
Aplicaciones
- Visualización de los datos de un sensor Lidar
- Mostrar imágenes de una cámara
- Visualización de algoritmos y datos
