Matplotlib Application Interfaces (API) #
Matplotlib ha due principali interfacce applicative o stili di utilizzo della libreria:
Un'interfaccia "Axes" esplicita che utilizza metodi su un oggetto Figure o Axes per creare altri artisti e creare una visualizzazione passo dopo passo. Questa è stata anche chiamata interfaccia "orientata agli oggetti".
Un'interfaccia "pyplot" implicita che tiene traccia dell'ultima figura e degli assi creati e aggiunge artisti all'oggetto che pensa che l'utente desideri.
Inoltre, un certo numero di librerie downstream (come pandas
e xarray ) offrono un plot
metodo implementato direttamente sulle loro classi di dati in modo che gli utenti possano chiamare data.plot()
.
La differenza tra queste interfacce può creare un po' di confusione, in particolare dati i frammenti sul Web che utilizzano l'una o l'altra, o talvolta più interfacce nello stesso esempio. Qui tentiamo di sottolineare come le interfacce "pyplot" e downstream si relazionano all'interfaccia esplicita "Axes" per aiutare gli utenti a navigare meglio nella libreria.
Interfacce Matplotlib native #
L'esplicita interfaccia "Axes" #
L'interfaccia "Axes" è il modo in cui viene implementato Matplotlib e molte personalizzazioni e messa a punto finiscono per essere eseguite a questo livello.
Questa interfaccia funziona istanziando un'istanza di una
Figure
classe ( fig
sotto), utilizzando un metodo
subplots
metodo (o simile) su quell'oggetto per creare uno o più
Axes
oggetti ( ax
sotto) e quindi chiamando i metodi di disegno sugli assi ( plot
in questo esempio):
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.subplots()
ax.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])
( Codice sorgente , png )
Chiamiamo questa un'interfaccia "esplicita" perché ogni oggetto è referenziato in modo esplicito e utilizzato per creare l'oggetto successivo. Mantenere i riferimenti agli oggetti è molto flessibile e ci consente di personalizzare gli oggetti dopo che sono stati creati, ma prima che vengano visualizzati.
L'interfaccia "pyplot" implicita #
Il pyplot
modulo mette in ombra la maggior parte dei
Axes
metodi di plottaggio per fornire l'equivalente di quanto sopra, in cui la creazione della figura e degli assi viene eseguita per l'utente:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])
( Codice sorgente , png )
Questo può essere utile, in particolare quando si eseguono lavori interattivi o semplici script. Un riferimento alla figura corrente può essere recuperato utilizzando
gcf
e agli assi correnti di gca
. Il pyplot
modulo conserva un elenco di figure e ogni figura conserva un elenco di assi sulla figura per l'utente in modo che quanto segue:
import matplotlib.pyplot as plt
plt.subplot(1, 2, 1)
plt.plot([1, 2, 3], [0, 0.5, 0.2])
plt.subplot(1, 2, 2)
plt.plot([3, 2, 1], [0, 0.5, 0.2])
( Codice sorgente , png )
è equivalente a:
import matplotlib.pyplot as plt
plt.subplot(1, 2, 1)
ax = plt.gca()
ax.plot([1, 2, 3], [0, 0.5, 0.2])
plt.subplot(1, 2, 2)
ax = plt.gca()
ax.plot([3, 2, 1], [0, 0.5, 0.2])
( Codice sorgente , png )
Nell'interfaccia esplicita, questo sarebbe:
import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 2)
axs[0].plot([1, 2, 3], [0, 0.5, 0.2])
axs[1].plot([3, 2, 1], [0, 0.5, 0.2])
( Codice sorgente , png )
Perché essere esplicito? #
Cosa succede se devi tornare indietro e operare su un vecchio asse che non è referenziato da plt.gca()
? Un modo semplice è chiamare di subplot
nuovo con gli stessi argomenti. Tuttavia, questo diventa rapidamente inelegante. Puoi anche ispezionare l'oggetto Figure e ottenere il suo elenco di oggetti Axes, tuttavia, che può essere fuorviante (anche le barre dei colori sono Axes!). La soluzione migliore è probabilmente quella di salvare una maniglia per ogni Axes che crei, ma se lo fai, perché non creare semplicemente tutti gli oggetti Axes all'inizio?
Il primo approccio è chiamare di plt.subplot
nuovo:
import matplotlib.pyplot as plt
plt.subplot(1, 2, 1)
plt.plot([1, 2, 3], [0, 0.5, 0.2])
plt.subplot(1, 2, 2)
plt.plot([3, 2, 1], [0, 0.5, 0.2])
plt.suptitle('Implicit Interface: re-call subplot')
for i in range(1, 3):
plt.subplot(1, 2, i)
plt.xlabel('Boo')
( Codice sorgente , png )
Il secondo è salvare un handle:
import matplotlib.pyplot as plt
axs = []
ax = plt.subplot(1, 2, 1)
axs += [ax]
plt.plot([1, 2, 3], [0, 0.5, 0.2])
ax = plt.subplot(1, 2, 2)
axs += [ax]
plt.plot([3, 2, 1], [0, 0.5, 0.2])
plt.suptitle('Implicit Interface: save handles')
for i in range(2):
plt.sca(axs[i])
plt.xlabel('Boo')
( Codice sorgente , png )
Tuttavia, il modo consigliato sarebbe quello di essere espliciti fin dall'inizio:
import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 2)
axs[0].plot([1, 2, 3], [0, 0.5, 0.2])
axs[1].plot([3, 2, 1], [0, 0.5, 0.2])
fig.suptitle('Explicit Interface')
for i in range(2):
axs[i].set_xlabel('Boo')
( Codice sorgente , png )
Interfacce "Data-object" della libreria di terze parti #
Alcune librerie di terze parti hanno scelto di implementare il plottaggio per i loro oggetti dati, ad esempio data.plot()
, è presente in pandas
, xarray e altre librerie di terze parti. A scopo illustrativo, una libreria a valle può implementare un semplice contenitore di dati che ha x
e y
dati memorizzati insieme, quindi implementa un plot
metodo:
import matplotlib.pyplot as plt
# supplied by downstream library:
class DataContainer:
def __init__(self, x, y):
"""
Proper docstring here!
"""
self._x = x
self._y = y
def plot(self, ax=None, **kwargs):
if ax is None:
ax = plt.gca()
ax.plot(self._x, self._y, **kwargs)
ax.set_title('Plotted from DataClass!')
return ax
# what the user usually calls:
data = DataContainer([0, 1, 2, 3], [0, 0.2, 0.5, 0.3])
data.plot()
( Codice sorgente , png )
Quindi la libreria può nascondere tutto il nocciolo all'utente e può creare una visualizzazione appropriata per il tipo di dati, spesso con buone etichette, scelte di mappe dei colori e altre utili funzionalità.
In quanto sopra, tuttavia, potrebbe non esserci piaciuto il titolo fornito dalla libreria. Per fortuna, ci restituiscono gli assi dal plot()
metodo e, comprendendo l'esplicita interfaccia degli assi, potremmo chiamare:
per personalizzare il titolo.ax.set_title('My preferred title')
Molte librerie consentono inoltre ai propri plot
metodi di accettare un
argomento facoltativo ascia . Questo ci consente di posizionare la visualizzazione in un Asse che abbiamo posizionato e forse personalizzato.
Sommario n.
Nel complesso, è utile comprendere l'interfaccia esplicita "Axes" in quanto è la più flessibile ed è alla base delle altre interfacce. Un utente di solito può capire come passare all'interfaccia esplicita e operare sugli oggetti sottostanti. Sebbene l'interfaccia esplicita possa essere un po' più prolissa da configurare, i grafici complicati spesso finiscono per essere più semplici rispetto al tentativo di utilizzare l'interfaccia implicita "pyplot".
Nota
A volte è fonte di confusione per le persone che importiamo pyplot
per entrambe le interfacce. Attualmente, il pyplot
modulo implementa l'interfaccia "pyplot", ma fornisce anche metodi di creazione di figure e assi di primo livello e, infine, attiva l'interfaccia utente grafica, se ne viene utilizzata una. Quindi pyplot
è ancora necessario indipendentemente dall'interfaccia scelta.
Allo stesso modo, le interfacce dichiarative fornite dalle librerie partner utilizzano gli oggetti accessibili dall'interfaccia "Axes" e spesso li accettano come argomenti o li restituiscono dai metodi. Di solito è essenziale utilizzare l'interfaccia "Axes" esplicita per eseguire qualsiasi personalizzazione della visualizzazione predefinita o per decomprimere i dati in array NumPy e passare direttamente a Matplotlib.
Appendice: Interfaccia "Assi" con strutture dati #
La maggior parte dei Axes
metodi consente ancora un altro indirizzamento API passando un
oggetto dati al metodo e specificando gli argomenti come stringhe:
import matplotlib.pyplot as plt
data = {'xdat': [0, 1, 2, 3], 'ydat': [0, 0.2, 0.4, 0.1]}
fig, ax = plt.subplots(figsize=(2, 2))
ax.plot('xdat', 'ydat', data=data)
( Codice sorgente , png )
Appendice: interfaccia "pylab" #
C'è un'altra interfaccia che è altamente sconsigliata, e cioè fondamentalmente fare . Ciò consente agli utenti di chiamare semplicemente . Sebbene conveniente, questo può portare a ovvi problemi se l'utente assegna inconsapevolmente a una variabile lo stesso nome di un metodo pyplot.from matplotlib.pyplot import *
plot(x, y)