Nota
Fare clic qui per scaricare il codice di esempio completo
Il ciclo di vita di un complotto #
Questo tutorial ha lo scopo di mostrare l'inizio, la parte centrale e la fine di una singola visualizzazione utilizzando Matplotlib. Inizieremo con alcuni dati grezzi e finiremo salvando una figura di una visualizzazione personalizzata. Lungo la strada proviamo a evidenziare alcune caratteristiche e best practice chiare utilizzando Matplotlib.
Nota
Questo tutorial è basato su questo eccellente post sul blog di Chris Moffitt. È stato trasformato in questo tutorial da Chris Holdgraf.
Una nota sulle interfacce esplicite e implicite #
Matplotlib ha due interfacce. Per una spiegazione dei compromessi tra le interfacce esplicite e implicite, vedere Matplotlib Application Interfaces (APIs) .
Nell'interfaccia esplicita orientata agli oggetti (OO) utilizziamo direttamente le istanze di
axes.Axes
per creare la visualizzazione in un'istanza di
figure.Figure
. Nell'interfaccia implicita, ispirata e modellata su MATLAB, utilizza un'interfaccia basata sullo stato globale che è incapsulata nel
pyplot
modulo per tracciare gli "assi correnti". Guarda i tutorial su pyplot per uno sguardo più approfondito all'interfaccia di pyplot.
La maggior parte dei termini è semplice, ma la cosa principale da ricordare è che:
La figura è l'immagine finale che può contenere 1 o più assi.
Gli assi rappresentano un grafico individuale (non confonderlo con la parola "asse", che si riferisce all'asse x/y di un grafico).
Chiamiamo metodi che eseguono il tracciato direttamente dagli assi, il che ci offre molta più flessibilità e potenza nella personalizzazione della nostra trama.
Nota
In generale preferiscono l'interfaccia esplicita rispetto all'interfaccia pyplot implicita per la stampa.
I nostri dati #
Useremo i dati del post da cui è stato derivato questo tutorial. Contiene informazioni sulle vendite per un certo numero di aziende.
import numpy as np
import matplotlib.pyplot as plt
data = {'Barton LLC': 109438.50,
'Frami, Hills and Schmidt': 103569.59,
'Fritsch, Russel and Anderson': 112214.71,
'Jerde-Hilpert': 112591.43,
'Keeling LLC': 100934.30,
'Koepp Ltd': 103660.54,
'Kulas Inc': 137351.96,
'Trantow-Barrows': 123381.38,
'White-Trantow': 135841.99,
'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)
Per iniziare #
Questi dati vengono naturalmente visualizzati come un grafico a barre, con una barra per gruppo. Per fare ciò con l'approccio orientato agli oggetti, prima generiamo un'istanza di figure.Figure
e
axes.Axes
. La figura è come una tela e gli assi sono una parte di quella tela su cui faremo una visualizzazione particolare.
Nota
Le figure possono avere più assi su di esse. Per informazioni su come eseguire questa operazione, vedere l' esercitazione Tight Layout .
fig, ax = plt.subplots()
Ora che abbiamo un'istanza di Axes, possiamo tracciarci sopra.
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
<BarContainer object of 10 artists>
Controllare lo stile #
Ci sono molti stili disponibili in Matplotlib per permetterti di adattare la tua visualizzazione alle tue esigenze. Per vedere un elenco di stili, possiamo usare
style
.
print(plt.style.available)
['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']
Puoi attivare uno stile con quanto segue:
plt.style.use('fivethirtyeight')
Ora rifacciamo la trama sopra per vedere come appare:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
<BarContainer object of 10 artists>
Lo stile controlla molte cose, come colore, larghezza di riga, sfondo, ecc.
Personalizzare la trama #
Ora abbiamo una trama con l'aspetto generale che vogliamo, quindi perfezioniamola in modo che sia pronta per la stampa. Per prima cosa ruotiamo le etichette sull'asse x in modo che vengano visualizzate più chiaramente. Possiamo accedere a queste etichette con il axes.Axes.get_xticklabels()
metodo:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
Se desideriamo impostare la proprietà di più elementi contemporaneamente, è utile utilizzare la pyplot.setp()
funzione. Questo richiederà un elenco (o molti elenchi) di oggetti Matplotlib e tenterà di impostare alcuni elementi di stile di ciascuno.
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
Sembra che questo abbia tagliato alcune delle etichette sul fondo. Possiamo dire a Matplotlib di fare automaticamente spazio agli elementi nelle figure che creiamo. Per fare questo impostiamo il autolayout
valore del nostro rcParams. Per ulteriori informazioni sul controllo dello stile, del layout e di altre funzionalità dei grafici con rcParams, vedere
Personalizzazione di Matplotlib con fogli di stile e rcParams .
plt.rcParams.update({'figure.autolayout': True})
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
Successivamente, aggiungiamo etichette alla trama. Per fare ciò con l'interfaccia OO, possiamo usare il Artist.set()
metodo per impostare le proprietà di questo oggetto Axes.
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
[(-10000.0, 140000.0), Text(0.5, 87.00000000000003, 'Total Revenue'), Text(86.99999999999997, 0.5, 'Company'), Text(0.5, 1.0, 'Company Revenue')]
Possiamo anche regolare la dimensione di questo grafico usando la pyplot.subplots()
funzione. Possiamo farlo con l' argomento della parola chiave figsize .
Nota
Mentre l'indicizzazione in NumPy segue la forma (riga, colonna), l' argomento della parola chiave figsize segue la forma (larghezza, altezza). Ciò segue le convenzioni della visualizzazione, che purtroppo sono diverse da quelle dell'algebra lineare.
fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
[(-10000.0, 140000.0), Text(0.5, 86.99999999999997, 'Total Revenue'), Text(86.99999999999997, 0.5, 'Company'), Text(0.5, 1.0, 'Company Revenue')]
Per le etichette, possiamo specificare linee guida di formattazione personalizzate sotto forma di funzioni. Di seguito definiamo una funzione che accetta un numero intero come input e restituisce una stringa come output. Se usati con Axis.set_major_formatter
o
Axis.set_minor_formatter
, creeranno e useranno automaticamente una
ticker.FuncFormatter
classe.
Per questa funzione, l' x
argomento è l'etichetta del segno di spunta originale ed pos
è la posizione del segno di spunta. Useremo solo x
qui, ma sono necessari entrambi gli argomenti.
def currency(x, pos):
"""The two arguments are the value and tick position"""
if x >= 1e6:
s = '${:1.1f}M'.format(x*1e-6)
else:
s = '${:1.0f}K'.format(x*1e-3)
return s
Possiamo quindi applicare questa funzione alle etichette sul nostro grafico. Per fare questo, usiamo l' xaxis
attributo dei nostri assi. Ciò ti consente di eseguire azioni su un asse specifico sulla nostra trama.
fig, ax = plt.subplots(figsize=(6, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
Combinazione di più visualizzazioni #
È possibile disegnare più elementi di trama sulla stessa istanza di
axes.Axes
. Per fare questo abbiamo semplicemente bisogno di chiamare un altro dei metodi plot su quell'oggetto axis.
fig, ax = plt.subplots(figsize=(8, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
# Add a vertical line, here we set the style in the function call
ax.axvline(group_mean, ls='--', color='r')
# Annotate new companies
for group in [3, 5, 8]:
ax.text(145000, group, "New Company", fontsize=10,
verticalalignment="center")
# Now we move our title up since it's getting a little cramped
ax.title.set(y=1.05)
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)
plt.show()
Salvare la nostra trama #
Ora che siamo soddisfatti del risultato della nostra trama, vogliamo salvarla su disco. Ci sono molti formati di file che possiamo salvare in Matplotlib. Per visualizzare un elenco delle opzioni disponibili, utilizzare:
print(fig.canvas.get_supported_filetypes())
{'eps': 'Encapsulated Postscript', 'jpg': 'Joint Photographic Experts Group', 'jpeg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps': 'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format', 'webp': 'WebP Image Format'}
Possiamo quindi utilizzare il figure.Figure.savefig()
per salvare la figura su disco. Nota che ci sono diversi flag utili che mostriamo di seguito:
transparent=True
rende trasparente lo sfondo della figura salvata se il formato lo supporta.dpi=80
controlla la risoluzione (punti per pollice quadrato) dell'output.bbox_inches="tight"
adatta i limiti della figura alla nostra trama.
# Uncomment this line to save the figure.
# fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")
Tempo di esecuzione totale dello script: (0 minuti 3,918 secondi)