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 pandase xarray ) offrono un plotmetodo 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 Figureclasse ( figsotto), utilizzando un metodo subplotsmetodo (o simile) su quell'oggetto per creare uno o più Axesoggetti ( axsotto) e quindi chiamando i metodi di disegno sugli assi ( plotin 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 )

../../_images/api_interfaces-1.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 pyplotmodulo mette in ombra la maggior parte dei Axesmetodi 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 )

../../_images/api_interfaces-2.png

Questo può essere utile, in particolare quando si eseguono lavori interattivi o semplici script. Un riferimento alla figura corrente può essere recuperato utilizzando gcfe agli assi correnti di gca. Il pyplotmodulo 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 )

../../_images/api_interfaces-3.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 )

../../_images/api_interfaces-4.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 )

../../_images/api_interfaces-5.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 subplotnuovo 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.subplotnuovo:

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 )

../../_images/api_interfaces-6.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 )

../../_images/api_interfaces-7.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 )

../../_images/api_interfaces-8.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 xe ydati memorizzati insieme, quindi implementa un plotmetodo:

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 )

../../_images/api_interfaces-9.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 plotmetodi 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 pyplotper entrambe le interfacce. Attualmente, il pyplotmodulo 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 Axesmetodi 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 )

../../_images/api_interfaces-10.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)