4.8. Disegnare grafici#

Il modulo plt può essere usato per produrre vari tipi di grafici. In generale le funzioni di questo modulo che generano un grafico basato su una serie di punti accettano come argomenti due liste contenenti rispettivamente le ascisse e le ordinate dei punti stessi. La funzione get_sorted_counts restituisce però una lista di coppie e non due liste di valori singoli. Se interpretiamo questa lista come una matrice, la trasposta di quest'ultima equivarrà a una lista che contiene esattamente le due liste che ci interessano. Per effettuare questa operazione risulta conveniente utilizzare il tipo di dato base messo a disposizione da numpy, np.array. Passando una lista (o una tupla, una lista di liste e così via) come argomento a np.array si crea un oggetto che corrisponde al corrispondente array. Su questo oggetto è possibile invocare il metodo transpose che restituisce il trasposto dell'array.

Nomenclatura

Tecnicamente, il metodo transpose restituisce una vista dell'array originale in modo che questo appaia trasposto. Ciò significa che non viene creato un nuovo oggetto e quindi le modifiche fatte al valore restituito andranno ad alterare anche l'array di partenza.

Va anche notato il fatto che se si tenta di trasporre un array monodimensionale transpose restituirà una vista identica all'argomento specificato.

import numpy as np

def get_sorted_counts(sequence):
    counts = {}

    for x in sequence:
        if x in counts:
            counts[x] += 1
        else:
            counts[x] = 1

    pairs = counts.items()
    return sorted(pairs, key=lambda p:p[1], reverse=True)

years = [1941, 1962, None, None, 1941,
         1964, None, 1940, 1941, 1961,
         None, 1963, None, 1963, 1981,
         None, None, 1962, 1979]

np.array(get_sorted_counts(years)).transpose()
array([[None, 1941, 1962, 1963, 1964, 1940, 1961, 1981, 1979],
       [7, 3, 2, 2, 1, 1, 1, 1, 1]], dtype=object)
np.array(get_sorted_counts(years)[1:]).transpose()
array([[1941, 1962, 1963, 1964, 1940, 1961, 1981, 1979],
       [   3,    2,    2,    1,    1,    1,    1,    1]])

Va notato come la prima coppia restituita da get_sorted_counts sia stata scartata tramite uno slicing in quanto fa riferimento a None e non a un anno, perché descrive il numero di casi in cui l'anno è un dato mancante. Usando una caratteristica di python è possibile assegnare le due liste ottenute direttamente a due variabili x e y:

a, b = (42, 102)
x, y = np.array(get_sorted_counts(years)[1:]).transpose()

Nomenclatura

Questa caratteristica di python, nota con il nome di unpacking, permette per esempio di scambiare i contenuti di due variabili a e b senza ricorrere a una variabile temporanea, utilizzando l'assegnamento a, b = b, a.

Le due variabili x e y possono dunque essere passate come argomento al metodo plt.bar per produrre un grafico a barre che visualizzi le frequenze assolute degli anni di prima apparizione:

import matplotlib.pyplot as plt

plt.bar(x, y)
plt.show()
../../_images/de618536c3ce850989f2af6b0bde813998c6c5d89b694a5f7da68fc06e03e131.png

Vale la pena commentare in modo approfondito le righe di codice appena eseguite, specificando la differenza tra generare e visualizzare un grafico. In generale, invocare un metodo in matplotlib ha l'effetto di modificare l'aspetto di un grafico (partendo ovviamente da un grafico vuoto). Ciò permette di sovrapporre diversi grafici, o di cambiare le etichette sugli assi e così via. Metodi come plt.bar visualizzano il grafico che corrisponde alla modifica apportata dal metodo eseguito, restituendo nel contempo dell'output testuale (una descrizione delle varie componenti del grafico stesso) che nella maggior parte dei casi non è particolarmente interessante. È per questo che l'ultima istruzione eseguita è plt.show(): questo metodo visualizza il grafico senza restituire alcunché.

La prima linea di codice fa riferimento a una caratteristica speciale di jupyter: tutte le linee che iniziano con il carattere % vengono chiamate line magic e permettono di effettuare operazioni accessorie, come per esempio l'interfacciamento con le operazioni di shell. In questo caso si tratta di una matplotlib magic che specifica che i grafici prodotti da matplotlib devono essere visualizzati direttamente nel notebook (senza questa operazione i grafici non verrebbero mostrati automaticamente e sarebbe necessario invocare altri metodi di matplotlib, per esempio per salvare i grafici su file system). Infine, la seconda linea ci permette di impostare le dimensioni dei grafici: i valori predefiniti genererebbero infatti delle figure un po' troppo grandi.

Nomenclatura

È sufficiente specificare la matplotlib magic una sola volta, all'inizio del notebook oppure prima di produrre il primo grafico da visualizzare. Da quel punto in avanti tutti i grafici verranno automaticamente mostrati nel notebook.