Guia rápido de plotagem - matplotlib¶
Plotagem genérica em modo explícito (interface “OO-like”)
import matplotlib.pyplot as plt
# fig é objeto matplotlib.Figure
# ax é objeto matplotlib.Axes
fig, ax = plt.subplots(nrows=3,
ncols=2,
sharex=True,
sharey=True,
num=1,
clear=True,
constrained_layout=True, # controle de interpadding
figsize=(4,2)
) 
Controle de razão de aspecto de eixos
fig, ax = plt.subplots(1,6,figsize=(10,2),constrained_layout=True)
fig.suptitle('Controle de razão de aspecto: ax.axis()',fontsize=10)
aspect_opt = [
'auto', # padrão
'equal',
'scaled',
'tight',
'square',
'personalizado'
]
for i, a in enumerate(ax.flatten()):
ax[i].plot([-1,0,4],[1,2,3],'o')
if i != 5:
ax[i].axis(aspect_opt[i])
title = "'" + aspect_opt[i] + "'"
ax[i].set_title(title, fontsize=8)
else:
# Limites personalizados com
ax[i].axis([-3,5,-2,4]) # 1a. forma: [xmin, xmax, ymin, ymax]
ax[i].set_xlim(-3,5); ax[5].set_ylim(-2,4); # 2a. forma
ax[i].set_title(aspect_opt[i], fontsize=8)
Visibilidade de eixos
fig, ax = plt.subplots(1,5,figsize=(10,2),constrained_layout=True)
fig.suptitle('Visibilidade de eixos',fontsize=8)
ax[0].get_xaxis().set_visible(False)
ax[0].plot([-1,0,1],[1,2,4],'o')
ax[1].get_yaxis().set_visible(False)
ax[1].plot([-1,0,1],[1,2,4],'o')
ax[2].set_axis_off() # axis('off')
ax[2].plot([-1,0,1],[1,2,4],'o')
ax[3].set_visible(True) # visibilidade do Artist
ax[3].plot([-1,0,1],[1,2,4],'o')
ax[3].spines['top'].set_visible(False)
ax[3].spines.bottom.set_visible(False)
ax[4].spines['left'].set_visible(False)
ax[4].spines.right.set_visible(False)
Mosaicos¶
Layouts com
GridSpecgs = fig.add_gridspec(m,n): cria mosaicofig.add_subplot(gs[m:,n:]): posiciona plot no mosaico
fig = plt.figure(figsize=(6,2),constrained_layout=True) # figura de background
fig.suptitle('Mosaico gridspec',fontsize=8)
gs = fig.add_gridspec(3,4)
fig_ax1 = fig.add_subplot(gs[0,:])
fig_ax2 = fig.add_subplot(gs[1:,0])
fig_ax3 = fig.add_subplot(gs[1:,1])
fig_ax4 = fig.add_subplot(gs[1,2:])
fig_ax5 = fig.add_subplot(gs[2,2:])
for eixo in fig.axes:
eixo.plot(1,1,'rs')
‘gridspec’ com larguras e alturas variáveis
fig = plt.figure(constrained_layout=True)
w = [2, 3, 1.5]
h = [1, 3, 2]
gs = fig.add_gridspec(ncols=3,
nrows=3,
width_ratios=w,
height_ratios=h)
for row in range(3):
for col in range(3):
ax = fig.add_subplot(gs[row, col])
label = f'Largura: {w[col]}\nAltura: {h[row]}'
ax.annotate(label, (0.1, 0.5), xycoords='axes fraction', va='center')
‘subgridspec’
f = plt.figure(constrained_layout=True)
# primeiro nível
gs0 = f.add_gridspec(1, 2)
# segundo nível
gs00 = gs0[0].subgridspec(2, 4)
gs01 = gs0[1].subgridspec(4, 2)
for a in range(2):
for b in range(4):
f.add_subplot(gs00[a, b])
f.add_subplot(gs01[b, a])
Eixos embutidos
fig, ax = plt.subplots(figsize=(2,2),constrained_layout=True)
x0, y0 = 0.5,0.5
width, height = 0.4,0.2
ax2 = ax.inset_axes(bounds=[x0,y0,width,height])
ax2.plot(0.5,0.5,'o')
ax2.get_xaxis().set_visible(False)
ax2.get_yaxis().set_visible(False)

Eixos apensados
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
# dado
data = np.random.normal(0,3,size=(20,20))
# figura
fig,ax = plt.subplots(figsize=(3,3))
im = ax.imshow(data)
# divisor
divider = make_axes_locatable(ax)
# eixos
ax_left = divider.append_axes("left", size="30%", pad=0.4)
ax_left.plot(data.flatten()[:10])
ax_top = divider.append_axes("top", size="20%", pad=0.1)
ax_top.plot(data.flatten(),c='r',lw=0.2)
ax_top.axis('tight')
ax_top.get_xaxis().set_visible(False); ax_top.get_yaxis().set_visible(False)
ax_right = divider.append_axes("right", size="25%", pad=0.05)
plt.colorbar(im,cax=ax_right)
ax_bot = divider.append_axes("bottom", size="35%", pad=0.3)
ax_bot.plot(data.flatten()[:20],c='b',lw=0.2)
ax_bot.axis('tight')
ax_bot.get_xaxis().set_visible(False); ax_top.get_yaxis().set_visible(False)

Estilo de linha e cap¶
fig, ax = plt.subplots(1,2,figsize=(6,2),constrained_layout=True)
x = np.linspace(-2,2)
# estilo de linha
linestyles = ['-',':','--','-.']
gap = 1
for lsi in linestyles:
ax[0].plot(x,x**2 + gap,ls=lsi)
gap += 1
ax[0].xaxis.set_visible(False)
ax[0].yaxis.set_visible(False)
# estilo de cap
for x, style in enumerate(['butt', 'round', 'projecting']):
xx = [x, x+0.5]
yy = [0, 0]
ax[1].plot(xx, yy, lw=12, color='tab:blue', solid_capstyle=style)
ax[1].plot(xx, yy, lw=1, color='black')
ax[1].plot(xx, yy, 'o', color='tab:red', markersize=3)
ax[1].xaxis.set_visible(False)
ax[1].yaxis.set_visible(False)
Marcadores¶
markers = ['.',',','o','s','p','d','h','P','D','H','X','*','<','>','^','v', \
'1','2','3','4','8','+','x','|','_','$...$',4,5,6,7, \
'$\\int$','$\\dagger$'
]
fig, ax = plt.subplots(figsize=(5,8),constrained_layout=True)
dom = np.linspace(0,1,30)
gap = 5
for i in range(len(markers)):
ax.plot(dom,dom + gap,ls='',lw=0.5,ms=10,marker=markers[i],markevery=5)
gap += 1
ax.axis('tight');
Controle de ticks e labels¶
Controle de ticks dado pelo módulo
matplotlib.tickerCustomização baseada em 4 pares de métodos básicos de locators e formatters:
ax.xaxis.set_major_locator()eax.yaxis.set_major_locator()ax.xaxis.set_minor_locator()eax.yaxis.set_minor_locator()ax.xaxis.set_major_formatter()eax.yaxis.set_major_formatter()ax.xaxis.set_minor_formatter()eax.yaxis.set_minor_formatter()
from matplotlib.ticker import MultipleLocator as ML
from matplotlib.ticker import ScalarFormatter as SF
fig, ax = plt.subplots(1,2,figsize=(8,1))
ax[0].set_xlim(0,3)
ax[0].xaxis.set_minor_locator (ML(0.05))
ax[1].set_xlim(1,2)
ax[1].xaxis.set_minor_locator (ML(0.01))
fig, ax = plt.subplots(figsize=(8,1))
ax.set_xlim(0,3)
ax.xaxis.set_minor_locator (ML(0.1))
ax.xaxis.set_minor_formatter (SF())
ax.tick_params(axis='x' ,which='minor', rotation=90, labelsize=8)
ax.set_xticklabels(ax.get_xticks(),weight='bold');/var/folders/ll/g0vl8b194pbfyp4cwpzz4p740000gn/T/ipykernel_9541/3390216078.py:6: UserWarning: set_ticklabels() should only be used with a fixed number of ticks, i.e. after set_ticks() or using a FixedLocator.
ax.set_xticklabels(ax.get_xticks(),weight='bold');

import matplotlib.pyplot as plt, matplotlib.ticker as mticker
x = list(range(10))
fig, ax = plt.subplots(figsize=(3,3))
ax.plot(x,x)
ax.xaxis.set_major_locator(mticker.FixedLocator([1.5,2.5,4.5]))
ax.set_xticklabels(['a','b','c'])
ax.xaxis.set_tick_params(rotation=45, labelsize=16) # Other solution: ax.tick_params(axis='x', rotation=25)
Controle de ticks em formato de datas¶
Controle dado pelo método
matplotlib.datesAplicar locators para dia, mês, ano, dia de semana etc.
import matplotlib.dates as mdates
import numpy as np
import datetime
period = 60
x = [datetime.date(2023,1,1) + datetime.timedelta(days=i) for i in range(period)]
y = np.random.rand(period)
fig, ax = plt.subplots(4,1,figsize=(8,4),constrained_layout=True)
# dia
ax[0].plot(x,y)
ax[0].xaxis.set_major_locator(mdates.DayLocator(interval=2)) # intervalo de 2 dias
ax[0].tick_params(axis='x' ,which='major', rotation=90, labelsize=8)
# semana
ax[1].plot(x,y)
ax[1].xaxis.set_major_locator(mdates.WeekdayLocator(interval=1))
ax[1].tick_params(axis='x' ,which='major', rotation=90, labelsize=8)
# mês
ax[2].plot(x,y)
ax[2].xaxis.set_major_locator(mdates.MonthLocator(interval=1))
# ano
period = 720
x2 = [datetime.date(2023,1,1) + datetime.timedelta(days=i) for i in range(period)]
y2 = np.random.rand(period)
ax[3].plot(x2,y2)
ax[3].xaxis.set_major_locator(mdates.YearLocator())
fig.suptitle('Controle de datas: dia; semana; mês; ano');
Aplicar formatters para tipos de strings. Placeholders aceitos:
%Y: Ano com século como um número decimal (por exemplo, 2023).%y: Ano sem o século como um número decimal (por exemplo, 23 para 2023).%m: Mês como um número decimal com zero à esquerda (por exemplo, 04 para abril).%d: Dia do mês como um número decimal com zero à esquerda (por exemplo, 15).%H: Hora (relógio de 24 horas) como um número decimal com zero à esquerda (por exemplo, 09).%M: Minuto como um número decimal com zero à esquerda (por exemplo, 05).%S: Segundo como um número decimal com zero à esquerda (por exemplo, 07).%A: Nome completo do dia da semana (por exemplo, “Domingo”).%a: Nome abreviado do dia da semana (por exemplo, “Dom”).%B: Nome completo do mês (por exemplo, “Abril”).%bou%h: Nome abreviado do mês (por exemplo, “Abr”).%j: Dia do ano como um número decimal com zero à esquerda (por exemplo, 105 para 15 de abril).%U: Número da semana do ano (domingo como o primeiro dia da semana) como um número decimal com zero à esquerda.%W: Número da semana do ano (segunda-feira como o primeiro dia da semana) como um número decimal com zero à esquerda.%Z: Nome do fuso horário (por exemplo, “UTC” ou “EST”).%%: Um caractere ‘%’ literal.
fig, ax = plt.subplots(4,1,figsize=(8,4),constrained_layout=True)
# dia
ax[0].plot(x,y)
ax[0].xaxis.set_major_locator(mdates.DayLocator(interval=5))
ax[0].xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax[0].tick_params(axis='x' ,which='major', rotation=45, labelsize=8)
ax[1].plot(x,y)
ax[1].xaxis.set_major_locator(mdates.DayLocator(interval=5))
ax[1].xaxis.set_major_formatter(mdates.DateFormatter('%A-%d'))
ax[1].tick_params(axis='x' ,which='major', rotation=45, labelsize=8)
ax[2].plot(x,y)
ax[2].xaxis.set_major_locator(mdates.DayLocator(interval=7))
ax[2].xaxis.set_major_formatter(mdates.DateFormatter('%Y, w%U d%j (%a) : %Z'))
ax[2].tick_params(axis='x' ,which='major', rotation=30, labelsize=8)
ax[3].plot(x,y)
ax[3].xaxis.set_major_locator(mdates.DayLocator(interval=10))
ax[3].xaxis.set_major_formatter(mdates.DateFormatter('%d/%b'))
ax[3].tick_params(axis='x' ,which='major', rotation=30, labelsize=8)
fig.suptitle('Formatação de datas');
Impressão de propriedades padronizadas/customizadas¶
def get_prop(prop):
from matplotlib import rcParams
from re import match
props = {}
for k,v in rcParams.items():
if match(prop,k):
props[k] = v
return props
# get_prop('axes')Impressão de paletas de cores disponíveis¶
def print_palette(opt):
"""Print matplotlib color pallete according to category.
Parameters:
opt (int): option for palette
1: uniform; 2: divergent; 3: ciclic; 4: generic
"""
seq_uniform = {'viridis', 'plasma', 'inferno', 'magma', 'cividis'}
seq_grp_1 = {'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', 'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', 'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn','YlGn'}
seq_grp_2 = {'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink', 'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia', 'hot', 'afmhot', 'gist_heat','copper'}
sequential = seq_uniform.union(seq_grp_1).union(seq_grp_2)
divergent = {'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr','seismic'}
ciclic = {'twilight', 'twilight_shifted', 'hsv'}
generic = {'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet', 'turbo', 'nipy_spectral','gist_ncar'}
selector = {1:sequential, 2:divergent, 3:ciclic, 4:generic}
for k,v in selector.items():
if k == opt: print(v)
Renderização de Latex¶
from matplotlib.pyplot import xlabel, ylabel
from matplotlib import rc
# ativa Latex
rc('text', usetex=True)
rc('axes', linewidth=2)
rc('font', weight='bold')
x = np.arange(4)
y = x
fig, ax = plt.subplots(figsize=(3,3))
ax.plot(x,x)
xlabel(r'\textbf{X-AXIS}', fontsize=10);
ylabel(r'f(x)', fontsize=10);
from matplotlib import rcdefaults
rcdefaults()

Pontos vs. pixels e resolução¶
O
matplotlibusa pontos e não pixels para medir o tamanho de figuras. Por padrão, 1 pt 1/72 inch.O controle de resolução da imagem pronta para publicação a ser gerada é feito pela alteração dos “pontos por polegada” (dots per inch), i.e. o argumento
dpina geração de imagens.
fig, ax = plt.subplots(constrained_layout=True, # controle de interpadding
figsize=(2,2),
dpi=50
)
ax.scatter(1,1,s=20)
fig, ax = plt.subplots(constrained_layout=True, # controle de interpadding
figsize=(2,2),
dpi=100
)
ax.scatter(1,1,s=20);

Trabalhando com objetos geométricos primitivos (patches)¶
Para o
matplotlib, umpatché um objeto da classeArtistque representa uma geometria primitiva 2D com face e aresta.Classes disponíveis:
Annulus,Arc,Arrow,CirclePolygon,Circle,ConnectionPatch,Ellipse,FancyArrowPatch,FancyArrow,FancyBboxPatch,Patch,PathPatch,Polygon,Rectangle,RegularPolygon,Shadow,StepPatch,Wedge,
Imprimindo subclasses de Patch¶
import matplotlib.patches as ptc
# Classes do módulo 'patches'. Nota: 'type' é a classe base para todas as classes em Python
all_ptc_cls = [cls for cls in ptc.__dict__.values() if isinstance(cls, type)]
# Filtra as classes que herdam de Patch
ptc_cls = [cls for cls in all_ptc_cls if issubclass(cls, ptc.Patch)]
# Imprime os nomes das classes de Patch
ptc_c = []
for cls in ptc_cls:
ptc_c.append(cls.__name__)
#print(cls.__name__,end=', ')
ptc_c = sorted(ptc_c)
Exemplos gerais¶
TODO
import matplotlib.pyplot as plt
import matplotlib.patches as ptc
fig, ax = plt.subplots(3,6,figsize=(12,6),constrained_layout=True)
for (i,_) in enumerate(ax.flatten()):
_.set_xticks([]); _.set_yticks([])
_.set_title(ptc_c[i], fontsize=10, fontname='Courier')
# --- ANNULUS
a1 = ptc.Annulus(xy=(0.2,0.2),
r=0.2, # circular: raio do círculo exterior
width=0.05, # espessura do anel
angle=30,
facecolor='green')
a2 = ptc.Annulus(xy=(0.7,0.5),
r=(0.2,0.3), # elíptico: eixo menor, eixo maior da elipse exterior
width=0.1,
angle=70,
facecolor='orange')
ax[0,0].add_patch(a1); ax[0,0].add_patch(a2)
# --- ARC
b1 = ptc.Arc(xy=(0.5,0.5),
width=0.2,
height=0.2,
angle=0,
theta1=0,
theta2=180,
edgecolor='red')
b2 = ptc.Arc(xy=(0.5,0.2),
width=0.8,
height=0.2,
angle=0,
theta1=180,
theta2=360,
facecolor='blue',
ls=':',
lw=2)
ax[0,1].add_patch(b1); ax[0,1].add_patch(b2)
# --- ARROW
c1 = ptc.Arrow(x=0.7,y=0.5, # cauda
dx=0.2,dy=0.0, # comprimento
width = 1.0, # escala
fill = False)
c2 = ptc.Arrow(x=0.4,y=0.4, # cauda
dx=-0.12,dy=-0.05, # comprimento
width = 1.0, # escala
fill = True)
ax[0,2].add_patch(c1); ax[0,2].add_patch(c2)
# --- CIRCLE
d1 = ptc.Circle(xy=(0.6,0.6),
radius=0.1)
d2 = ptc.Circle(xy=(0.3,0.3),
radius=0.05,
fill=False,
lw=3,
edgecolor='k')
ax[0,3].add_patch(d1); ax[0,3].add_patch(d2)
# --- CIRCLEPOLYGON
e1 = ptc.CirclePolygon(xy=(0.5,0.5),
radius=0.45,
edgecolor='r',
resolution=20,
lw=4)
e2 = ptc.CirclePolygon(xy=(0.5,0.5),
radius=0.25,
resolution=10,
facecolor='k',
edgecolor='w',
lw=4)
ax[0,4].add_patch(e1); ax[0,4].add_patch(e2)
# --- ELLIPSE
center = (0.5, 0.5)
width = 0.8
height = 0.4
angle = 30
g1 = ptc.Ellipse(center, width, height, angle=angle, edgecolor='blue', facecolor='none', linewidth=2)
ax[1,0].add_patch(g1)
# --- FANCYARROW
start_point = (0.1, 0.1)
end_point = (0.7, 0.7)
h1 = ptc.FancyArrow(start_point[0], start_point[1],
end_point[0] - start_point[0], end_point[1] - start_point[1],
color='green', width=0.03, head_width=0.1, head_length=0.1)
ax[1,1].add_patch(h1);
# --- RECTANGLE
f1 = ptc.Rectangle(xy=(0.2,0.4),
width=0.6,
height=0.3,
angle=0,
color='red',
lw=2)
ax[2,1].add_patch(f1);
Aplicação: bandeira do Brasil¶
import matplotlib.pyplot as plt
import matplotlib.patches as ptc
# altura/largura
a = 3; b = 1.6*a
# área de plotagem
fig, ax = plt.subplots(figsize=(b,a))
# retângulo
rec = ptc.Rectangle(xy=(0,0),
height=a,
width=2.5*a,
angle=0,
facecolor='g',
edgecolor='g')
# losango
los_vertices = [(0.05,0.5), (0.5,0.1), (0.95,0.5), (0.5,0.9)]
los = ptc.Polygon(los_vertices,
closed=True,
facecolor='y',
edgecolor='y')
# círculo
circ = ptc.Circle(xy=(0.5,0.5),
radius = 0.2,
facecolor='b',
edgecolor='b')
# arco
center = (0.4, 0.0)
width = 1.15
height = 1.15
angle_range = (58, 100) # Start and stop angles (degrees)
rotation_angle = 0 # Rotation angle (degrees)
arc = ptc.Arc(center, width, height,
angle=rotation_angle,
theta1=angle_range[0],
theta2=angle_range[1],
edgecolor='w',
lw=4.5)
# estrelas
# adiciona patches
ax.add_patch(rec)
ax.add_patch(los)
ax.add_patch(circ)
ax.add_patch(arc)
# decorações
ax.spines['top'].set_visible(False); ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False); ax.spines['left'].set_visible(False)
ax.set_xticks([]); ax.set_yticks([]);
# Ver: https://micromath.com.br/a-geometria-da-bandeira-do-brasil/
Desenhando com hachuras/tramas (hatches)¶
Patching + hatching
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2,5,figsize=(10,3),constrained_layout=True)
hatches = ['//', '\\','|','-','+','x','o','O','.','*']
def rect(hatch):
return ptc.Rectangle(xy=(0,0),
height=1,
width=2.5,
angle=0,
edgecolor='w',
facecolor='lightblue',
linewidth=2,
hatch=hatch)
for (i,_) in enumerate(ax.flatten()):
_.set_xticks([]); _.set_yticks([])
_.set_title(hatches[i], fontsize=10, fontname='Courier')
_.add_patch(rect(hatches[i]))
Ploting + hatching
import matplotlib.pyplot as plt
categorias = ['A', 'B', 'C', 'D']
valores = [1, 4, 3, 5]
np.random.seed(110)
x = np.random.rand(20); y = np.random.rand(20)
fig, ax = plt.subplots(1,2,figsize=(8,3))
ax[0].bar(categorias, valores, hatch='//', edgecolor='black', color='lightgreen')
ax[1].scatter(x, y, s=500, c='red', edgecolors='b', linewidth=1, hatch='o');
