menu
Paolo Avogadro

Matplotlib - appunti

Posted on 07/11/2021, in Italiano. Reading time: 86 mins

Matplotlib

Queste sono le mie (Paolo Avogadro) note basate sul video di Derek Banas riguardo a Matplotlib. Oltre agli esempi suggeriti aggiungo dei miei test e considerazioni. Qualunque errore e’ esclusivamente dovuto ad una mia erronea interpretazione dei comandi. Lo scopo di queste note non e’ di presentare esempi perfettamente funzionanti, ma serve a me come spunto per ricordare i comandi di Matplotlib, e il modello mentale che io ho sul pacchetto. La versione originale di queste note ha la forma di un Jupyter Notebook e quindi possono esserci dei riferimenti ai notebook all’interno del testo. Dopo avere imparato Matplotlib puo’ essere interessante impararare ad usare Seaborn.

Cerco di ricostruire gli esempi presentati e fare delle piccole varianti per capire meglio. Queste note suppongono che ci sia una certa conoscenza di base di come fare i grafici al computer, per esempio partendo da Gnuplot.

Notazione:

  • cerco di usare l’evidenziatore per i comandi
  • cerco di usare il grassetto per i termini principali

Micro-riassunto:

Ci sono 2 modi principali per fare un grafico:

  1. modo veloce: con le funzioni di plotting, per esempio: plt.plot(x_1, y_1) (dove x_1 e x_2 sono due oggetti contenenti lo stesso numero di variabili). Si possono inoltre aggiungere delle funzioni per controllare le label, il titolo ecc.

  2. modo esteso:

    • prima si definisce una figure, per esempio: fig_1 = plt.figure(figsize=(5,4), dpi =100); pensa alla figure come un’immagine bianca.
    • poi si costruisce uno (o piu’) axes (assi) con un metodo delle figure: axes_1 = fig_1.add_axes([0.1,0.1,0.9,0.9]) (dove specifichiamo la posizione degli assi all’interno della figura). Gli assi determineranno la posizione del grafico. Per esempio se hai un solo quadrante per il tuo grafico puoi immaginare gli assi come un rettangolo (vuoto all’interno).
    • A questo punto si fa partire un grafico, usando un metodo degli assi, per esempio: axes_1.plot(x_1,y_1); Nota che questi metodi sono in pratica le stesse funzioni del punto 1 (solo che vengono chiamati come metodi dell’asse).

Nota

  • se non sei in un jupyter notebook dovrai usare un plt.show()
  • se sei su un notebook invece, serve un magic command (e’ una di quelle cose decorate con il percentuale), ci sono vari di questi comandi, tra cui:
    1. %matplotlib inline (questo fa apparire delle immagini png statiche nel notebook)
    2. %matplotlib notebook (si possono fare zoom delle immagini)
    3. %matplotlib tk (tkinter GUI)

Una lista di termini utili:

  • alpha=0.75 definisce la trasparenza
  • lw=2 larghezza delle linee del grafico
  • ls ='-.' line style, se e’ una linea continua, oppure trattino e punto, ecc…
  • marker = 'o' marker sono i punti di gnuplot. Cosa viene messo nei punti? in questo caso dei cerchietti =o)
  • markersize=7 la grandezza dei punti
  • markerfacecolor ='y' il colore dell’interno dei punti
  • markeredgecolor='k' il colore dei contorni dei punti
  • markeredgewidth=2 la larghezza del contorno dei punti
  • projection='3d' argomento per quando si creano degli assi e devono avere un 3D
  • goog_df = pd.read_csv('GOOG.csv', index_col = 0, parse_dates=True) trasforma del testo in datetime!
  • facecolor e’ il colore dello sfondo di un’immagine

Metodi di FIGURE:

  • fig.tight_layout() oppure, plt.tight_layout() serve per evitare sovrapposizioni per esempio i numeri degli assi trasbordino
  • fig_3.savefig('ultimoPlot.png') salvare a file una figura!

Metodi degli Assi

  • plt.xticks(np.linspace(0,5,5), ('Tom', 'Dick', 'Harry', 'Sally', 'Sue')) tics (o ticks) sull’asse x. Per non avere ticks: plt.xticks([]) (non ho messo nulla nella lista = non ci sono ticks)
  • axes_3.set_xlim([0,3]) definisce i limiti sull’asse x (set xlim[1:100])
  • axes_4.set_xlabel('temp') label degli assi
  • axes_3.grid(False, color='r', dashes=(0,2,1,2)) mette una griglia sullo sfondo, occhio che color e’ il colore della griglia non dello sfondo. plt.grid(False) e plt.grid(b=None) tolgono la griglia
  • axes_3.set_facecolor('w') colore dello sfondo (bianco in questo caso)
  • axes_4.set_title('da Pandas: IceCream') titolo
  • axes_1.legend(loc =0 ) # Loc=0 e’ la migliore location scelta da lui`

Tipi di disegno (possono essere chiamati come metodi degli assi o funzioni plt):

  • axes_4.plot(x_2, y_2) disegno standard in cui ci sono i punti e posso unirli, cambiarli ecc.
  • plt.bar(x_2, y_2, width=1.5); barchart (come istogramma ma sulle x possono essere categorici)
  • plt.stem(x_2, y_2, '-.') impulsi, interessante si puo’ indicare il tipo di linea
  • plt.hist(arr3ok, bins= 7, density=True, stacked =False); istogrammi (raggruppa i valori sull’asse delle x in bins)
  • plt.pie() piechart TORTE (gurada sotto perche’ servono un po’ di dettagli)
  • axes_13.scatter(dr_arr, test_arr, s=cc_arr_sm, c=color_arr, alpha=0.2 ) scatterplot valori sull’asse delle x, y, dimensione punti, colori dei punti, trasparenza)
  • axes_9.scatter3D(x_3,y_3,z_3, c=z_3, cmap='Blues'); scatterplot 3D
  • axes_9.contour3D(x_4,y_4,z_4, 20, cmap='Blues'); 3D contorno, curve di livello, isoipse
  • axes_9.plot_wireframe(x_4,y_4,z_4, cmap='Blues'); wireframe e’ il grafico 3D standard di gnuplot, collega tutti i punti
  • axes_9.plot_surface(x_4,y_4,z_4, rstride=1, cstride=1, cmap='Blues', edgecolor='r'); 3D, collega i punti e colora le tegole

Consiglio: in un Jupyter notebook usa shift-tab su una funzione per vederne la sua descrizione (prima devi cliccare sulla cella e poi avere il cursore sulla funzione stessa).

Consiglio questo articolo contiene trucchi su jupyter notebook e alternative a Matplotlib.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
#%matplotlib notebook
%reload_ext autoreload
%autoreload 2             

Functional Plot

Cominciamo con un’immagine semplice in cui

  • c’e’ il titolo: plt.title('ciao')
  • ci sono i nomi degli asssi: plt.xlabel('Days')
  • c’e’ un grafico: plt.plot(x_1, y_1)

Quando faccio un disegno, voglio che tutte le coordinate x siano in un contenitore (lo stesso vale per le coordinate y). Questi “contenitori” devono contenere lo stesso numero di oggetti, altrimenti per un punto avrei solo la coordinata x o solo la y… quindi mi manca il punto!

x_1 = np.linspace(0,5,10)  # genera un Numpy array con 10 float equispaziati tra 0 e 5
y_1 = x_1 **2              # genera un Numpy array che e' il quadrato del primo 
plt.plot(x_1, y_1);
plt.title('ciao');
plt.xlabel('Days');
plt.ylabel('Days squared');
#plt.show()                  # se non siamo in jupyter notebook

png

Domanda: posso passare delle liste ad un plt.plot()?

Risposta: si’ certo! posso anche graficare delle liste che contengano delle stringhe. Se il contenitore di stringhe e’ una lista, allora esiste un ordine per le stringhe e questo ordine verra’ usato nella visualizzazione. Per un set invece non esiste un ordine e si ha un errore TypeError: unhashable type: ‘set’

l1= [1,2,3,4]
l2= [3,4,5,6]
l3= ['a','b','e','d']
d1 = {"apple", "banana", "cherry"}
plt.plot(l1,l3);
#plt.plot(l1,d1)   # non funge!

png

plt.subplot() molti grafici in modo veloce

Qui vediamo come mettere piu’ di un grafico vicino all’altro. Nel dettaglio usando subplot potremo costuire una griglia, in ogni casella della griglia verra’ messo un grafico.

Il comando plt.subplot(1,2,1) fa questo tipo di lavoro.

  1. il primo argomento e’ il numero di righe della griglia (in questo caso c’e’ solo una riga)
  2. il secondo argomento e’ il numero di colonne della griglia .
  3. il terzo argomento e’ l’indice del grafico. L’indice ci dice in quale casella della griglia stiamo mettendo il subplot. L’ordine seguito e’ lo stesso che si ha quando si legge: da SINISTRA a DESTRA da SOPRA a SOTTO.

Vediamo un esempio:

# nota che se anche il terzo argomento e' 2 il grafico appare al primo posto, perche'
# non ce ne sono 2! E' un po' come se cadesse a sinistra se ci sono dei buchi?
plt.subplot(1,2,2)        # questo ci dice che abbiamo una riga e 2 colonne
plt.plot(x_1,y_1, 'r');   # r = red 

png

plt.subplot(1,2,1)        # questo ci dice che abbiamo una riga e 2 colonne
plt.plot(x_1,y_1, 'r')    # r = red 
plt.subplot(1,2,2)        # se metto 1 mi sovrappone con il primo ma mi dice che c'e' qualcosa di strano
plt.plot(x_1,y_1, 'b')
[<matplotlib.lines.Line2D at 0x2de659e5c40>]

png

plt.subplot(2,2,1)        # 
plt.plot(x_1,y_1, 'r')    #  
plt.subplot(2,2,2)        # 
plt.plot(x_1, y_1-y_1**2, 'b')
plt.subplot(2,2,4)
plt.plot(x_1, -y_1, 'g');
plt.tight_layout()              # evita sovrapposizione dei numeri dei grafici!

png

Figure e axes

  • Una figure e’ un oggetto su cui poi si mette il grafico (lo vedo come la tela bianca su cui fare il disegno)
  • contiene tutti i ‘plot elements’
  • puo’ contenere molti axes (assi), che in pratica sono gli assi che definiscono il disegno vero e proprio, in quanto i punti sono riferiti agli assi.
  • posso definire la sua larghezza e lunghezza in inch (inch=2.54 cm), probabilmente posso cambiare scala: figsize=(5,4)
  • posso anche definire la risoluzione in dpi
  • ATTENTO se definisci il numero di dpi, quando lo visualizzi come un png, questo definisce la dimensione della figura a video! quindi sembra che figsize non funzioni!
fig_1 = plt.figure(figsize=(5,4), dpi =100);
<Figure size 500x400 with 0 Axes>

Axes

L’oggetto axes (come indica il nome) identifica la posizione, la forma, e tutte le caratteristiche degli ASSI di un grafico. Se non facciamo esplicitamente un grafico, ci saranno solo le due fracce perpendicolari (gli assi) con dentro nulla. Possiamo i plot (grafici) sono dei metodi degli assi! La logica e’ quindi che siano un oggetto in funzione di dove sono gli assi (e ha senso, quando uno fa un grafico su un foglio, prima disegna gli assi, e poi puo’ definire la posizione dei punti che compongono il grafico. In questo senso quindi il plot e’ stato definito come un metodo di un axes. Nota che posso mettere piu’ di un axes su una singola figure. Anche questo e’ intuitivo, posso mettere 2 grafici sullo stesso foglio, poi i punti di un grafico saranno riferiti ad un paio di assi e quelli del secondo ad un altro paio di assi. Gli assi definiscono il sistema di riferimento “inerziale” che determina la posizione dei punti!

Gli assi vengono costruiti su una figure tramite questo metodo:

axes_1 = fig_1.add_axes([0.1,0.1,0.9,0.9])

Significa che axes_1 sara’ un rettangolo il cui:

  • punto in basso a sx ha coordinate 0.1, 0.1 (rispetto a fig_1). Ovvero, la figure e’ un rettangolo, anche gli axes sono un rettangolo, il cui punto in basso a sinistra si trova nelle coordinate che sono il 10% delle x e il 10% delle y del punto in basso a sx della figure.
  • punto in alto a dx ha coordinate 0.9,0.9 (rispetto a fig_1) In questo modo ho un grafico che e’ piu’ piccolo del “canvas” definito da fig_1.

  • (nel video) non e’ chiaro come ha fatto l’esponente 2 sulla x. Io devo usare i comandi Latex

Attenzione, io avevo messo il comando fig_1 = plt.figure(figsize=(5,4), dpi =100) in una cella diversa da dove facevo il axes.plot. Per questo non vedevo nulla!! Bisogna creare la figura nella stessa cella di Jupyter!

Quindi ricapitolando:

  • creo un oggetto figura ( me lo immagino come un foglio bianco di una certa dimensione)
  • creo un oggetto axes che e’ ottenuto da un metodo della figura ( e’ il grafico vero e proprio, definito dagli assi sopra, sotto e destra e sinistra. Al suo interno posso poi mettere dei disegni tramite il metodo plot)
  • tramite metodi di axes aggiungo delle caratteristiche come le label
  • tra i metodi di un axes c’e’ plot (e altri tipi di grafico che potrei fare direttamente con plt). Chiamando un metodo che disegna da un axes, il grafico viene messo su questo axes.
  • posso aggiungere piu’ di un grafico sullo stesso axes, basta chiamare piu’ volte un metodo che disegna sull’axes.
  • nota che si deve fare un axes.plot per ognuno dei disegni che voglio compaiano nella figura!
fig_1 = plt.figure(figsize=(5,4), dpi =100) # istanzio una FIGURA chiamata 'fig_1' 
axes_1 = fig_1.add_axes([0.1,0.1,0.9,0.9])  # istanzio un AXES (axes_1), della figura 'fig_1'
axes_1.set_xlabel('Days new')               # LABEL degli assi
axes_1.set_ylabel('Days squared new')       # LABEL degli assi
axes_1.set_title('Ciao new')                # TITOLO degli assi
axes_1.plot(x_1, y_1, label = 'x/x$^2$')    #  GRAFICO 1  (all'interno di axes_1)
axes_1.plot(y_1, x_1, label = 'x^2/x')      #  GRAFICO 2  (all'interno di axes_1)
axes_1.legend(loc =0 )                      # Loc=0 e' la migliore location scelta da lui
# 1=alt dx; 2=alto sx; 3=basso sx, 4 basso dx 
# oppure si fornisce una tupla di x e y dall'angolo in basso a sinistra
tu = (0.3, 0.4) # (tupla) questi valori sono in frazione rispetto alla grandezza totale, vedi sotto 
axes_1.legend(loc=tu );  # posizione della legenda

png

Molte curve: versione veloce

se devo fare un grafico veloce, basta che passo le x e y di tutti i grafici in ordine al plot, in questo modo verranno visualizzati tutti! Se non metto color='black' di default le due curve avranno colori diversi

plt.plot(x_1, y_1, x_1, y_1/3);                   # disegna le 2 funzioni 

png

Axes innestati

Voglio ora inserire piu’ di un axes nella stessa figura. In pratica aggiungo un axes all’esempio precedente.

Per fare questo devo creare un altro axes, proprio perche’ in questo caso i dati si riferiscono ad assi diverse che devono essere definite.

Ricapitolando:

  • nell’esempio sopra ci sono una curva blu e una arancione, sono comunque riferite allo stesso axes. Questi axes vanno da 0 a 25 (circa).
  • se voglio inserire una figura nuova, i punti di questa figura saranno riferiti a un nuovo sistema di assi, ho quindi bisogno di inserire questi nuovi assi, creando un nuovo oggetto axes (con un nome diverso)
  • dovro’ quindi indicare dove si collocano questi nuovi assi rspetto alla figure
  • dovro’ anche indicare la loro grandezza, anche in questo caso rispetto alla figure

Testo nella figura

  • per inserire un testo nel disegno si usa il metodo text di axes.
  • Le coordinate sono riferite all’axes e partono dal basso a sinistra.
  • Nota che nel disegno sotto ho 2 axes, e il messaggio e’ riferito ad axes_2. Questo e’ ovvio perche’ e’ chiamato come un metodo di questo axes
  • Nota inoltre che axes_2.text(0,40,'message') fa uscire dal disegno, in quanto per il disegno l’asse delle y arriva solo fino a circa 25!

nell’esempio di qui sotto:

  • il primo axis contiene due curve
  • il secondo axis contiene una curva
fig_1 = plt.figure(figsize=(5,4), dpi =100)     # FIGURA 1
assi_1 = fig_1.add_axes([0.1,0.1,0.9,0.9])      # ASSI_1 
assi_1.set_xlabel('Days new')           
assi_1.set_ylabel('Days squared new')
assi_1.set_title('Ciao new')
assi_1.plot(x_1, y_1, label = 'x/x$^2$')        #  GRAFICO 1 (degli "ASSI_1")
assi_1.plot(y_1, x_1, label = 'x^2/x')          #  GRAFICO 2 (degli "ASSI_1")
assi_1.legend(loc =0 )                          # Loc=0 e' la migliore location scelta da lui

########   costruisco i secondi assi #####################
assi_2 = fig_1.add_axes([0.45, 0.45,0.4,0.3])   # ASSE 2
assi_2.set_xlabel('Days new')                      
assi_2.set_ylabel('Days squared new')
assi_2.set_title('Ciao dentro')
assi_2.plot(x_1, y_1, 'r')  #  GRAFICO 2        # GRAFICO 1 (degli "ASSI_2")  


#assi_2.text(0,40, 'Message')  # testo
assi_2.text(0,40, 'Message')  # testo

Text(0, 40, 'Message')

png

subplots() Una griglia di grafici

OCCHIO: plt.subplots()$\neq$plt.subplot() (il primo termina in s)

Il singolo comando subplots in pratica costruisce 2 oggetti:

  • una figure
  • una array di assi (ma un array di numpy puo’ contenere degli oggetti strani? non erano solo numeri? no! basta che in tutti gli oggetti siano dello stesso tipo: omogeneita’ degli array).
  • devo quindi descrivere/inizializzare ognuno dei possibili axes dell’array, altrimenti ho solo gli assi senza nessun disegno dentro.

In pratica e’ una specie di scorciatoia per ordinare facilmente degli axis in una figure in modo che siano esattamente alle posizioni della griglia che viene definita con il comando, per esempio indicando il numero di colonne e di righe. Altrimenti avrei potuto istanziare una figura, e istanziare tanti axes stando attento a metterli nel posto giusto all’interno della figura.

Attenzione se voglio mettere degli axes aggiuntivi (oltre all’array di axes iniziale), posso farlo, occhio pero’ che si riferiranno tutti alla figure per quanto riguarda la posizione e non avranno un particolare ordinamento o forma. Dovro’ essere io a stare attento a metterli nel posto corretto e con la forma corretta!

  • il comando plt.tight_layout() aiuta a non fare sovrapporre le label.

  • Attento che devi usare il nome della figura corretto fig_2
  • Attento: non usare un nome gia’ usato per un altro axes, come axes_2
  • Attento: la dimensione del subplot e’ riferita al figsize, non all’axes di cui e’ subplot. Per questo trasborda!
  • Attento: se costruisci un nuovo axes viene messo sopra l’axis genitore, e per questo lo (puo’) coprire.
  • Di default un axes non e’ trasparente!
fig_2 , axes_2 = plt.subplots(figsize=(8,4), nrows=1, ncols= 3) 
plt.tight_layout()                    # evita la sovrapposizione delle label
axes_2[1].set_title('Plot 2')
axes_2[1].set_xlabel('x')
axes_2[1].set_ylabel('x quadro')
axes_2[1].plot(x_1, y_1)

# Nuovo AXES che non fa parte dell'array creato con   subplots

axes_3 = fig_2.add_axes([0.45, 0.45,0.4,0.4])
axes_3.set_xlabel('Days new')
axes_3.set_ylabel('Days squared new')
axes_3.set_title('Ciao straripante')
axes_3.plot(x_1, y_1, 'r')  #  GRAFICO 2

axes = fig_2.add_axes ([0.085,0.15,0.2,0.7])
axes.plot(x_1,y_1, 'co')
axes.set_title('Dentro')
Text(0.5, 1.0, 'Dentro')

png

f , a = plt.subplots(figsize=(8,4), nrows=1, ncols= 3) 
plt.tight_layout()          

############ Axes Centrale ###############
a[1].set_title('Centrale')
a[1].set_xlabel('x')
a[1].set_ylabel('x quadro')
a[1].plot(x_1, y_1)

############ Axes Ciao Dentro ############
a1 = f.add_axes([0.45, 0.45,0.4,0.4])
a1.set_xlabel('Days now')
a1.set_ylabel('Days squared new')
a1.set_title('Tra centro e sinistra')
a1.plot(x_1, y_1, 'r')  #  GRAFICO 2 della figura centrale

############ Axes Sinistro ###############
a[0].set_title('Sinistra')
a[0].set_xlabel('x')
a[0].set_ylabel('x quadro')
a[0].plot(x_1, -y_1,'g')

############ Axes Piccolo sinistra  ######
a0 = f.add_axes([0.1, 0.25,0.2,0.2])
a0.set_xlabel('Days old')
a0.set_ylabel('Days squared new')
a0.set_title('Piccolo Sinistra')
a0.plot(x_1, y_1, 'r')  #  GRAFICO 2 della figura centrale
[<matplotlib.lines.Line2D at 0x2de66e3a190>]

png

Colori e Apparenza

I colori di default sono:

  • r = red
  • c = cyan
  • m = magenta
  • y = yellow
  • k = black
  • w = white

Inoltre

  • color=”0.75” crea un 75% gray (e’ una percentuale di black)
  • si possono usare i colori con hexcodes color=”#eeefff”
  • si possono usare i colori tipo color=”burlywood” che si trovano a https://en.wikipedia.org/wiki/Web_colors

  • lw come gnuplot, ma devo mettere l’uguale, p.es. lw=2
  • ls ‘-.’ si trovano qui: https://matplotlib.org/3.1.0/gallery/lines_bars_and_markers/linestyles.html
  • marker sono i punti: https://matplotlib.org/3.3.3/api/markers_api.html
  • markersize = grandezza del punto
  • markerfacecolor = colore di riempimento del punto
  • makeredgecolor = colore del bordo del punto
fig_3 = plt.figure(figsize=(6,4))
axes_3  = fig_3.add_axes([0,0,1,1])
axes_3.plot(x_1, y_1, color='navy', alpha=0.75, lw=2, ls ='-.', marker = 'o', 
           markersize=7, markerfacecolor ='y', markeredgecolor='k', markeredgewidth=2)
[<matplotlib.lines.Line2D at 0x2de66eaa970>]

png

Grandezza degli assi e background

I comandi per gestire gli assi assomigliano a quelli di gnuplot, ma solo un po’ piu’ “verbose”, in cui si deve scrivere di piu’.

Possimo anche mettere una griglia e il background color.

  • axes_3.set_xlim([0,3]) limiti asse x
  • axes_3.grid(True, color='0.6', dashes=(5,2,1,2)) caratteristiche della griglia (NON dello sfondo!), dashes mette delle linee tratteggiate attraverso il disegno. Quindi qui sono le righe che partono da un tic e arrivano dall’altra parte del disegno
  • axes_3.set_facecolor('#FAEBD7') colore di sfondo
fig_3 = plt.figure(figsize=(3,4) )
axes_3  = fig_3.add_axes([0,0,1,1])
axes_3.plot(x_1, y_1, color='navy', alpha=0.75, lw=2, ls ='-.', marker = 'o', 
           markersize=7, markerfacecolor ='y', markeredgecolor='k', markeredgewidth=2)

axes_3.set_xlim([0,3])
axes_3.set_ylim([0,25])

#axes_3.grid(True, color='0.6', dashes=(5,2,1,2))   # mettiamo una griglia non lasciamo vuoto 
axes_3.grid(False, color='r', dashes=(0,2,1,2)) 

#axes_3.set_facecolor('#FAEBD7')
axes_3.set_facecolor('w')

png

Salvare una figura a file

strano quando lavoravo con Seaborn sembrave che il save dovesse avvenire nella stessa cella dove si faceva il disegno.

  • Basta mettere il nome dell’estensione e lui salva correttamente nel formato corrispondente
fig_3.savefig('ultimoPlot.png')

Pandas

Qui usiamo l’ICE CREAM data table (che diventera’ un DataFrame). Ho copiato il dataframe del video.

  • Assegno dei nomi alle colonne del csv, mentre leggo il file: ics_df = pd.read_csv('icecream.csv', names=['temps', 'sales']) . Nota che io ho usato i nomi sales e temps (temperatures). Lui li aveva con la prima lettera in maiuscolo. Temp e’ in Farenheit, e sales e’ in unita’ di gelato.

  • Se non usassi il parametro names=... lui prenderebbe la prima riga e la trasformerebbe nei nomi delle colonne (e i valori della prima riga non sarebbero accessibili)!

  • Osservazione: il metodo dei DataFrame sort_values(by='temps') lavora inplace, quindi modifica il df!

ics_df = pd.read_csv('icecream.csv', names=['temps', 'sales'])
ics_df.head()
temps sales
0 37 292
1 40 228
2 49 324
3 61 376
4 72 440

Attento sort_values() lavora inplace

ics_df = ics_df.sort_values(by='temps')  # LAVORA INPLACE

A questo punto lui fa delle cose che sembrano non necessarie. Prende e converte il DataFrame in un array di Numpy. Poi prende e scrive le x e le y da questo array di numpy. In effetti ho notato in una sezione sotto che alle volte e’ davvero meglio avere dei numpy array invece che i dataframe, in particolare per evitare dei valori strani sull’asse delle x.

#   con numpy array ###############
#  np_arr = ics_df.values    # prende solo i valori, rimuove le etichette
#  x_2 = np_arr[:,0]         # seleziono colonna 0
#  y_2 = np_arr[:,1]         # seleziono colonna 1  
###################################
# Alternativa:
x_2 = ics_df.temps # non sono array di np, ma serie di Pandas vanno bene lo stesso
y_2 = ics_df.sales # ricorda puoi usare l nome di una colonna per selezionare tutta le colonna come se fosse un attributo

#x_2 = np.array(ics_df.temps) # NON serve... ora, ma in alcuni casi si'
#y_2 = np.array(ics_df.sales) # NON serve... ora, ma in alcuni casi si'

ok ma fino a qui, dove ha usto il fatto che sia Pandas?

fig_4 = plt.figure(figsize=(6,4))
axes_4 = fig_4.add_axes([0,0,1,1])  # prendo tutto lo spazio, dall'angolo in basso a sx a quello in alto a dx
axes_4.set_title('da Pandas: IceCream')
axes_4.set_xlabel('temp')
axes_4.set_ylabel('sales')
axes_4.plot(x_2, y_2, marker='+');  # ho messo sui punti le crocette come in Gnuplot

png

Annotare la figura

Se voglio mettere delle annotazioni nel grafico, come per esempio delle frecce, devo usare un metodo degli axes chiamato annotate. Vediamo nel dettaglio il comando: axes_4.annotate('Good Month', xy=(83, 536), xytext=(60,520), arrowprops= dict(facecolor='black', shrink=0.0, width=0.5))

  • 'Good Month' e’ il testo che viene inserito
  • xy=(83,536) e’ il punto di arrivo della freccia
  • xytext=(60,520) e’ il punto di partenza del testo orizzontale

All’interno di arrowprops si hanno vari parametri (si deve passare un dizionario con tutti gli argomenti)

  • facecolor= ‘black’
  • shrink=0.5 indica quanto piu’ corta deve essere la freccia, rispetto alla lunghezza massima che va dalla fine del testo al punto di arrivo della freccia.
  • width=0.5 possiamo anche allargare la larghezza
fig_4 = plt.figure(figsize=(6,4))
axes_4 = fig_4.add_axes([0,0,1,1])  # prendo tutto lo spazio, dall'angolo in basso a sx a quello in alto a dx
axes_4.set_title('da Pandas: IceCream')
axes_4.set_xlabel('temp')
axes_4.set_ylabel('sales')
axes_4.plot(x_2, y_2)
axes_4.annotate('Good Month', xy=(83, 536), xytext=(60,520),
                arrowprops= dict(facecolor='black', shrink=0.0, width=0.5))
Text(60, 520, 'Good Month')

png

bar() Barchart sotto il grafico

bar() e’ un metodo di plt

Se voglio fare aggiungere anche le barchart sotto il grafico, basta disegnare ANCHE loro!

Attento ho fatto 2 plot:

  1. il primo e’ dato da axes_4.plot(x_2, y_2) ed e’ passato come un metodo degli assi
  2. il secondo e’ un grafico veloce ed e’ una funzione di matplotlib: plt.bar(x_2, y_2, width=1.5);
fig_4 = plt.figure(figsize=(6,4))
axes_4 = fig_4.add_axes([0,0,1,1])  # prendo tutto lo spazio, dall'angolo in basso a sx a quello in alto a dx
axes_4.set_title('da Pandas: IceCream')
axes_4.set_xlabel('temp')
axes_4.set_ylabel('sales')
axes_4.plot(x_2, y_2)
axes_4.annotate('Good Month', xy=(83, 536), xytext=(60,520),
                arrowprops= dict(facecolor='black', shrink=0.0, width=0.5))
plt.bar(x_2, y_2, width=1.5);

png

Impulsi stem() e proprieta’ setp()

In gnuplot mettevo with impulses quando volevo che il grafico avesse delle linee verticali che partono dall’asse x e raggiungono ogni punto. Il comando descritto qui sopra bar() non e’ l’ideale per ottenere questo risultato in quanto la larghezza dell’impulso puo’ creare problemi, meglio usare la funzione:

plt.stem()

mentre posso decidere di colorare l’asse sotto tramite la funzione set property:

plt.setp()

Questa funzione puo’ essere usata per vari oggetti!

fig_4 = plt.figure(figsize=(6,4))
axes_4 = fig_4.add_axes([0,0,1,1])  # prendo tutto lo spazio, dall'angolo in basso a sx a quello in alto a dx
axes_4.set_title('da Pandas: IceCream')
axes_4.set_xlabel('temp')
axes_4.set_ylabel('sales')
axes_4.plot(x_2, y_2)
axes_4.annotate('Good Month', xy=(83, 536), xytext=(60,520),
                arrowprops= dict(facecolor='black', shrink=0.0, width=0.5))
markerline, stemlines, baseline = plt.stem(x_2, y_2, '-.')
plt.setp(baseline, 'color', 'r', 'linewidth', 2)
[None, None]

png

TeX - regular expressions

possiamo usare Latex per scriver formule matematiche usando per esempio $\frac{1}{2}$

  • IMPORTANTE nota che nel tutorial ha usato: r'$\alpha \beta \gamma$' non ha semplicemente messo ‘’ perche’ cosi’ prende le regular expression, come il dollaro e lo slash.

Ovvero la scrittura r’ciao $\frac{2}{3}’ crea una stringa che pero’ ha delle regular expression che vengono valutate ed eseguite.

  • basta poi ricordare i comandi di Latex
  • il metodo .text degli ‘axes’ mette ha all’inizio le coordinate (separate da una virgola), poi una virgola con il testo da inserire.
fig_5 = plt.figure(figsize=(5,4), dpi=100)
axes_5 = fig_5.add_axes([0.1, 0.1, 0.9, 0.9])                       # costruisco un axes

axes_5.text(0,23, r'$\alpha~ \beta~ \gamma ~ \frac{1}{2} ~\Sigma$') # prima le coordinate del testo, poi il testo

axes_5.plot(x_1, y_1)
[<matplotlib.lines.Line2D at 0x2de66ff15e0>]

png

Istogrammi plt.hist()

Alcuni argomenti utili per gli istogrammi:

  • stacked=True

Simuliamo probabilita’ di lancio di 2 dadi. Ci sono 11 possibili valori per la somma:

  • 1+1 =2 I
  • 1+2 =3 II
  • 1+3 =4 III
  • 1+4 =5 IV
  • 1+5 =6 V
  • 1+6 =7 VI
  • 2+6 =8 VII (nota che tutti gli altri valori di (2+qualcosa) danno dei risultati gia’ ottenuti)
  • 3+6 =9 VIII
  • 4+6 =10 IX
  • 5+6 =11 X
  • 6+6 =12 XI Come altri parametri:
  • density=True mostra la frequenza di ogni bin (se e’ falso mostra il conteggio)
  • stacked=True cosa fa?

Attento: ricorda che il numero di bins puo’ portare a risultati MOLTO fuorvianti. Per esempio se scegliamo bins=7 otteniamo un oggetto bicefalo attorno al centro. Se invece scegliamo bins=11 otteniamo una campana!

arr_1 = np.random.randint(1,7,5000) # genera 5000 numeri interi tra 1 e 6
arr_2 = np.random.randint(1,7,5000) # genera 5000 numeri interi tra 1 e 6
arr_3 =arr_1+arr_2
arr3ok = arr_3
plt.hist(arr3ok, bins= 7, density=True, stacked =False);

png

plt.hist(arr_3, bins= 11, density=True, stacked =True);

png

ax[0].hist() Axes e istogrammi

Qui sotto provo a combinare axes e istogrammi.

  • Ho supposto di poter usare il metodo hist() direttamente su un asse invece che dover usare un plt.hist, ovvero: axes.hist(...)

Funge!

fig , ax = plt.subplots(figsize=(8,4), nrows=1, ncols= 2) 
#plt.tight_layout()          
ax[0].hist( arr_3, bins= 11, density=True, stacked =True);
ax[1].hist( arr_3, bins= 11, density=False, stacked =False);

png

altri argomenti che si possono passare:

  • Range deve essere una tupla con il range di cui si e’ interessati
  • cumulative =True costruisce la CDF (cumulative distribution function) dati i valori. Attento non me lo prendeva (diceva qualcosa riguardo l’oggetto kernel). Non ho lanciato tutte le altre celle, ma solo quelle iniziali con gli header e quelle della cella Istogramma
  • histtype= 'step' genera un grafo con le linee (ma vuoto)
  • color = 'orange' colora di arancione…
  • orientation = 'horizontal' gira di 90 gradi l’istogramma posso combinare anche due istogrammi insieme come con gli altri plot.
plt.hist(arr_3, bins= 11, density=True, stacked =True, cumulative=True,
         histtype='step', color='blue', orientation= 'horizontal');

png

Bar charts

Che differenza c’e’ tra un grafo a barre e un istogramma? de facto nell’istogramma si mettono le frazioni e le “barre” sono attaccate l’una all’altra. In un bar chart invece si hanno i numeri e le barre non sono attaccate l’una all’altra, questo perche’ sull’asse delle x spesso non si hanno dei valori numerici, ma categorici (come nell’esempio riportato sotto, dove l’ordine delle colonne e’ sostanzialmente arbitrario).

Per un grafo a barre, si chiama la funzione seguente:

plt.bar(spc, m_eng,width=larghezza, label='maschi', edgecolor ='k')

  • il primo argomento contiene la lista/tupla con i nomi che appaiono sull’asse delle x (dato che spesso lo usiamo per variabili categoriche dobbiamo indicare le label), oppure le posizioni delle barre (se ho le posizioni dovro’ poi aggiungere le label sull’asse)
  • Attento se nella prima tupla ci sono dei nomi, allora le loro posizioni sono equispaziate automaticamente. Se io aggiungo un altro bar chart, questo secondo viene messo dopo quelle gia’ esistenti.
  • Attento se invece nella prima tupla ci sono dei float (che quindi definisce la posizione delle barre), allora facendo un secondo plot, quest’ultimo segue le proprie posizioni.
  • Attento pui mettere 2 bar chart, uno con variabili categoriche e uno con float. Le posizioni delle categoriche sono messe automaticamente in integer (che partono quindi da zero). Nell’esempio qui sotto, la barra di nuclear ha posizione sull’asse delle x uguale a 0, hydro e’ in posizione 1, …
  • il secondo argomento contiene l’array che con le altezze della barchart
  • yerr ??? serve per la barra che indica l’errore, ed e’ un array che deve contenere tanti oggetti quante sono le barre
  • width larghezza della barra (altrimenti da’ errore? )
  • label non la vedo… scritta forse bisogna attivarla. Anche nel video non fungeva
## energia francese
x = ['nuclear', 'hydro', 'coal', 'gas', 'solar', 'wind', 'other']
per_1 = [71,10,3,7,2,4,3]   # percentuale
variance = [8,3,1,3,1,2,1]  # varianza per anno

plt.bar(x, per_1, color='purple',yerr=variance, label='prova')  
<BarContainer object of 7 artists>

png

## energia francese
x = ['nuclear', 'hydro', 'coal', 'gas', 'solar', 'wind', 'other']
per_1 = [71,10,3,7,2,4,3]   # percentuale
variance = [8,3,1,3,1,2,1]  # varianza per anno
plt.bar(x, per_1, color='purple',yerr=variance, label='prova')  
y = [el + '   ' for el in x]
z = ['test1', 'test2', 'test3']
z2 = [1, 2, 10]
per_2 = [34,43,21]
plt.bar(z2, per_2, color='red', label='prova') 
<BarContainer object of 3 artists>

png

y
['nuclear   ',
 'hydro   ',
 'coal   ',
 'gas   ',
 'solar   ',
 'wind   ',
 'other   ']

Bar Chart affiancate

Qui sotto mettiamo due bar chart affiancate una da parte all’altra. In questo modo possiamo confrontare dati diversi. E’ fondamentale che la posizione dell’array che definisce l’asse delle x della seconda bar chart sia spostato rispetto all’asse delle x della prima bar chart di una quantita’ tale da non fare sovrapporre (a meno di volerlo). Per esempio di puo’ usare lo stesso array maggiorato della larghezza della barchart!

m_eng = (76,85,86,88,93)  # percentuale maschi ingegneri
f_eng = (24,15,14,12,7)   # femmine

spc = np.arange(5)
larghezza =0.45
plt.bar(spc    , m_eng,width=larghezza, label='maschi', edgecolor ='k')
plt.bar(spc+larghezza, f_eng,width=larghezza, label='femmine', edgecolor ='k')
#plt.xticks(spc + larghezza/2, ('Aero', 'Chem', 'Civil', 'Elect', 'Mec'))
plt.xticks(spc   , ('Aero', 'Chem', 'Civil', 'Elect', 'Mec')) ;   # altrimenti lo mette a meta' strada del primo istogramma

png

Bar Chart impilate (stacked)

Qui mettiamo le barre una sopra l’altra.

Diamo un’occhiata alla list comprehension che viene usata:

ind = [x for x, _ in enumerate(t_type)]

  • enumerate restituisce delle coppie: posizione, oggetto.
  • Non ci serve l’oggetto ma solo la posizione, qunidi non spreco una variabile y, metto _
  • Prendi tutte le posizioni che ci sono nell’oggetto t_type
  • questa volta la label e’ apparsa nella legenda.

ATTENTO

  • il parametro bottom dice cosa c’e’ sotto di questa barchart. In particolare possiamo indicare un array, o anche una somma di array come nell’esempio di cui sotto. Se mettiamo un array che viene disegnato nella barchart, allora stiamo in pratica impilando il nuovo barchart sopra quello dell’altro array
#############   DATI ######################
t_type= ['kind', 'elem', 'sec', 'special']
print(type(t_type))
m_teach = np.array([2,20,44,14])
f_teach = np.array([98,80,56,86])
n_teach = np.array([12,14,13,15])

ind = [x for x,_ in enumerate(t_type)]  # list comprehension. Vedi sopra per come si legge


plt.bar(ind, n_teach, width=larghezza, label='nuovo', bottom=f_teach+m_teach) # posso metterne piu' di uno sotto
plt.bar(ind, m_teach, width=larghezza, label='maschi', bottom=f_teach) # posso metterne piu' di uno sotto
plt.bar(ind, f_teach, width=larghezza, label='femmine')
plt.legend(loc='lower right');   # non ideale....
#plt.legend(loc=0);                # manco questo... 
<class 'list'>

png

Torte - Pie chart, plt.pie()

Vediamo i diagrammi a torta. Per questi si usa il comando:

wedges, texts, autotexts = plt.pie(poke_num, explode=explode, labels=types, colors=colors, autopct='%1.0f%%', shadow=True, startangle=140, textprops =dict(color='w'))

Dal punto di vista sintattico la funzione pie() restituisce 3 oggetti:

  1. le wedges (gli spicchi o cunei del diagramma a torta).
  2. i texts
  3. gli autotext

In questo caso abbiamo prima costruito la figure, poi gli axes ed infine abbiamo chiamato la funzione pie. E’ un po’ diverso dal solito quando si usava un metodo dell’axes.

  • Nota che in un diagramma a torta, intuitivamente, i valori di larghezza (angolo) associati ad ogni fetta vengono convertiti in percentuali dell’angolo giro. Questo perche’ ci si aspetta che tutti i valori di un array riempiano tutto il cerchio.

  • explode a questa keyword si deve passare un array di float con tanti ingressi quante sono le fette. Il valore di ogni ingresso dice di quanto viene “estratta” la fetta alla posizione corrispondente, vedi l’esempio sotto.

  • nell’esempio sotto ci sono 2 array: types e pole_num, questi devono avere il medesimo numero di ingressi.

  • labels=types e’ un parametro che indica le etichette associate ad ogni fetta

  • autopct indica come vengono arrotondati i numeri associati alle larghezze, gli si deve passare come valore una stringa che indica un formato.

  • shadow=true e’ il parametro che dice se mettiamo l’ombra

  • colori ha usato un trucco notevole, ha fatto scrivere dei valori in formato RGB tramite il generatore di numeri casuali. Tre numeri indicano un colore, e lui indicando il range dei colori tra [0, 0.5] ha fatto si’ che vengono scuri. Ha scelto i colori scuri perche’ la scritta viene in bianco!

  • Occhio, avevo fatto un errore di sintassi ma non semplice da osservare. Nell’array types che contiene dei nomi tra virgolette, in un caso, quando andavo a capo ho dimenticato di mettere una virgola tra un nome e l’altro e lui mi ha preso solo uno dei nomi

  • bbox_to_anchor = (1,0,0.5,1) serve per spostare di 1 e 1/2 a destra della piechart (???)

import random
fig_6  = plt.figure(figsize=(8,5))
axes_6 = fig_6.add_axes([0.1,0.1,0.9,0.9])

#Vogliamo un diagramma a torte
types = ['water', 'normal', 'flying', 'grass', 'psychic','bug',
        'fire', 'poison', 'ground','rock','fighting', 'dark', 'steel',  
        'electric','dragon','fairy','ghost','ice']

poke_num =[133, 109, 101, 98, 85, 77, 68, 66, 65, 60, 57, 54, 53, 51, 50, 50, 46, 40]

colors = []
for i in range(18):         # per il testo bianco genero i coloi delle fette in modo che siano scuri
    rgb = (random.uniform(0,.5) , random.uniform(0,.5) , random.uniform(0,.5)  )
    colors.append(rgb)
    
explode = [0] * 18     # ho creato una lista di 18 zeri (non mi ricordavo questo modo!)
explode[0] = 0.2       # esplodi la prima fetta ma solo di 0.2

#print(len(types));
#print(len(poke_num));

wedges, texts, autotexts = plt.pie(poke_num, explode=explode, labels=types, colors=colors,
                                  autopct='%1.0f%%', shadow=True,
                                  startangle=140, textprops =dict(color='w'))

plt.legend(wedges, types, loc='right', bbox_to_anchor = (1,0,0.5,1)); #  sposto dalla piechart

png

Serie Temporali

Qui vediamo come fare un grafico con una serie temporale in cui i vari punti sono etichettati con un timestamp. Puo’ essere necessario togliere dei giorni particolari e risulta piu’ comodo sapere la data piuttosto che trovare il punto corrispondente della time series.

Il database usato viene da Yahoo riguardo i dati di google, GOOG.csv. (non e’ esattamente come mostrato nel video ma si trova in fretta). Per trovarlo cerca con google “yahoo google stock”, seleziona le date e fai download (nota che la frequenza e’ giornaliera).

All’inizio si carica il file con read_csv di Pandas, poi si trasforma la tabella in un array di numpy (sono tutti valori numerici). Lui usa un metodo dei DataFrame di Pandas che io non uso mai: tp_numpy(). Io invece faccio semplicemente np.array().

Ho provato a fare un giro piu’ semplice, cercando di plottare i dati direttamwente DAL DataFrame, di cui seleziono le colonne volute (ma avendo prima selezionato le righe, vedi sotto). Sfortunatamente sull’asse delle x vengono dei valori sballati come tics, il grafico e’ pero’ corretto. Questo e’ probabilmente il motivo per cui lui preferisce trasformare tutto in array di Numpy.

Scrubbing data: per esempio vogliamo togliere alcune vacanze, ha controllato due date che sono vacanze e vuole escluderlo. Usa datetime. La funzione datetime.datetime(2020,5,25) crea una data in un oggetto specifico, che puo’ poi essere trasformato a seconda delle esigenze, p.es g/m/a o m/g/a ecc.

Poi costruisce un array di date che vanno da una data iniziale ad una finale, tramite un metodo di pandas: pd.bdate_range, si puo’ passare il parametro frequency freq ='C' in questo caso, ma no so cosa sia il valore ‘C’!

holidays e’ il nome di un altro parametro che appunto corrisponde alle vacanze e possiamo passare un array/tupla contentente dei dati in formato datetime che vengono riconosciuti. ATTENTO la mia versione non riconosce questo parametro. Ho riscritto tutto e ora funge.

Problema: non so quando ha preso lui le date da Yahoo, io ho piu’ giorni.

Problema2 se uso tutti questi giorni, i tics che vengono segnati sono troppi e sotto l’asse viene un guazzabuglio di linee. Devo modificare per ottenere le date corrette.

import datetime
goog_data = pd.read_csv('GOOG.csv')    # IMPORTO il file GOOG.csv che ho salvato nella dir corrente
goog_data_np = goog_data.to_numpy()    # trasformo in np.array
#goog_data_np =np.array(goog_data)     # modo alternativo di trasformare
goog_cp = goog_data_np[:,4]

holidays = [datetime.datetime(2020,5,25)  , datetime.datetime(2020,8,19) ] # creo una lista con due date che saranno vacanze

date_arr = pd.bdate_range(start ='5/20/2020' ,
                            end ='8/19/2020' , 
                           freq ='C', 
                       holidays = holidays) 

date_arr_np = date_arr.to_numpy()
goog_data.head(3)
Date Open High Low Close Adj Close Volume
0 2019-08-21 1193.150024 1199.000000 1187.430054 1191.250000 1191.250000 740700
1 2019-08-22 1194.069946 1198.011963 1178.579956 1189.530029 1189.530029 947500
2 2019-08-23 1181.989990 1194.079956 1147.750000 1151.290039 1151.290039 1687000

Selezionare righe secondo delle date

Seguo questo esempio per selezionare le date: https://stackoverflow.com/questions/29370057/select-dataframe-rows-between-two-dates

Creo una mask per selezionare le date che voglio e che devono seguire quelle indicate nel bdate_range. In pratica creo una maschera, ovvero un array di bool che poi posso passare a loc! In questo modo solo gli ingressi in cui la maschera e’ vera vengono selezionati.

  • Problema I: devo paragonare delle date… in formati magari diversi
  • Soluzione I uso pd.to_datetime() che e’ una goduriosa funzione di Pandas che converte una stringa in un oggetto di tipo datetime. Questo oggetto e’ una data ed e’ possibile paragonare due datetime per vedere chi viene prima o dopo! Questa funzione e’ particolarmente VANTAGGIOSA in quanto riconosce tanti tipi diversi di formato in cui possiamo scrivere una data e li converte i un unico oggetto!
  • Alternativa usa parse_dates (vedi il Finance Module)

Una volta ottenuto un modo per paragonare le date posso creare una lista con valori booleani in cui seleziono le date (basta un loop), chiamo questo oggetto maschera

  • Problema II la maschera cosi’ creata non e’ un oggetto iterabile che si possa mettere nel metodo loc di pandas. Devo tasformarlo in un oggetto non iterabile
  • Soluzione II basta costruire una funzione che prende come input qualcosa e quando lo sputa in output gli metto un tuple davanti!
  • DUBBIO ehi ma nel codice non ho usato la tupla, anzi se dove faccio finanza metto la tupla mi da errore, sembra che una Series di pandas vada bene

Attenzione pero’ la maschera cosi’ creata e’ un oggetto mutabile e questo non puo’ essere usato come ingresso della funzione loc (di PANDAS) perche’ questa necessita oggetti immutabili da cui puo’ estrarre una hashtable.

link utili:

loc: https://stackoverflow.com/questions/29370057/select-dataframe-rows-between-two-dates

to_datetime: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html

convertire lista in tupla: https://www.geeksforgeeks.org/python-convert-a-list-into-a-tuple/

# PROBLEMA  I
# qui sotto prendo la colonna Date del dataFrame
# poi converto i valori ivi contenuti in un oggetto di tipo datetime con to_datetime
# a questo punto li paragono ai valori entro cui voglio che siano le date, sempre
# sfruttando la funzione di pandas pd.to_datetime

mask = (   ( pd.to_datetime(goog_data['Date']) >= pd.to_datetime('5/20/2020')) 
         & ( pd.to_datetime(goog_data['Date']) <= pd.to_datetime('8/19/2020')) )



# PROBLEMA II
# l'oggetto mask non  e' di tipo immutabile e quindi non puo' essere usato come iteratore
# devo trasformarlo in unoggetto immutabile

def convert(list): 
    return tuple(list) 

mask_t= convert(mask)

#print(type(mask_t) , 'tipo maschera')    # controllo
#print(len(goog_data.loc[mask]))          # controllo che i due oggetti abbiano lo stesso numero di righe  

new = goog_data.loc[mask]   # loc NON lavora inplace <===================
new_np = new.to_numpy()
goog_cp = new_np[:,4]       #  


# PROBLEMA III 
# Costruisco un array con le date corrispondenti in modo che io possa poi disegnarle

fig_7 = plt.figure(figsize=(8,5))  # creiamo la figura/canvas come al solito
axes_7 = fig_7.add_axes([0.1,0.1, 0.9, 0.9])  # il grafico non copre tutta la figura, lasciamo un po' di padding
plt.plot(date_arr_np, goog_cp);

#plt.plot(new.Date, new.Close) # questo fa vedere sbagliato i tics sotto

png

Tabelle

Questo non e’ cosi’ interessante, la cosa che trovo piu’ utile e’ come girare le date sull’asse delle x. Copio il pezzo di notebook scritto da Banas qui sotto:

# Format column data to 2 decimals
goog_data['Open'] = pd.Series([round(val, 2) for val in goog_data['Open']], 
                              index = goog_data.index)
goog_data['High'] = pd.Series([round(val, 2) for val in goog_data['High']], 
                              index = goog_data.index)
goog_data['Low'] = pd.Series([round(val, 2) for val in goog_data['Low']], 
                              index = goog_data.index)
goog_data['Close'] = pd.Series([round(val, 2) for val in goog_data['Close']], 
                              index = goog_data.index)
goog_data['Adj Close'] = pd.Series([round(val, 2) for val in goog_data['Adj Close']], 
                              index = goog_data.index)

# Get most recent last 5 days of stock data
stk_data = goog_data[-5:]
stk_data

# Define headers
col_head = ('Date','Open','High','Low','Close','Adj Close','Volume')

stk_data_np = stk_data.to_numpy()
stk_data_np

# Add padding around cells in table
plt.figure(linewidth=2, tight_layout={'pad':.5}, figsize=(5,3))

# Get rid of axes and plot box
axes_8 = plt.gca()
axes_8.get_xaxis().set_visible(False)
axes_8.get_yaxis().set_visible(False)
plt.box(on=None)

# np.full returns an array filled with 0.1
# cm is a colormap object we are using to use a default blue color
# matplotlib.org/3.1.0/tutorials/colors/colormaps.html
ccolors = plt.cm.Blues(np.full(len(col_head), 0.2))

# Receives data, loc, list of column headers, column header color as array of colors
# You can also add rowLabel, rowColours, rowLoc: Text alignment
the_table = plt.table(cellText=stk_data_np, loc='center', colLabels=col_head,
                     colColours=ccolors)
# Set table font size
the_table.set_fontsize(14)
the_table.scale(3, 2.5)

C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\pylabtools.py:132: UserWarning: Tight layout not applied. The left and right margins cannot be made large enough to accommodate all axes decorations. 
  fig.canvas.print_figure(bytes_io, **kw)

png

ScatterPlot

Qui ci sono dei dati relativi al Coronavirus. E’ importante che ci sia uniformita’ di grandezza per quanto riguarda gli array che vanno plottati:

  • ci sono 26 nazioni
  • ci sono 26 tassi di mortalita’
  • ci sono 26 valori di casi confermati giornalieri
  • ci sono 26 dimensioni dei punti

Nota che i questo caso non costruisco la figura e poi gli assi. Questo perche’ viene fatto automaticamente dal comando plt.scatter. Ci sono 2 vie per ottenere lo stesso grafico:

  1. costruisco la fig, e gli assi e uso scatter come metodo sull’asse creato
  2. uso plt.scatter e lui automaticamente crea gli assi!

Argomenti dello scatterplot:

  • prima si mettono i valori dell’asse delle x (e’ un np.array)
  • poi l’array per i valori dell’asse delle y (anche questo un np.array lungo quanto quello sopra)
  • s per size (dei punti): NON e’ come gnuplot che accettava le abbreviazioni, qui il parametro si chiama SOLO s!
  • c per color (dei punti)
  • alpha e’ in pratica il livello di trasparenza, in questo caso e’ fondamentale in quanto alcuni punti andranno a sovrapporsi
# Numpy array con i nomi delle nazioni
cnt_arr = np.array(['Australia','Brazil','Canada','Chile','France','Germany','Greece',
                   'Iceland','India','Iran','Italy','Mexico','New Zealand','Nigeria',
                   'Norway','Pakistan','Peru','Russia','Saudi Arabia','Singapore',
                   'South Africa','Spain','Sweden','Turkey','UK','US'])
# Tasso mortalita per 100k casi Coronavirus
dr_arr = np.array([1.8,53,24.5,56.5,45.4,11.2,2.2,
                   2.8,4,24.6,58.6,46.3,.5,.5,
                   4.9,2.9,83.3,11,10.4,.5,
                   21.5,61.6,56.9,7.3,62.4,52.9])
# Numero giornaliero di casi confermati (Tests)
test_arr = np.array([110,7197,600,1862,1636,1103,35,
                   10,295,1658,1226,2490,8,243,
                   48,1395,1101,4447,1443,280,
                   2830,1602,447,1205,1546,24988])
# Dimensione del punto dei casi confermati
cc_arr = np.array([24236,3456652,125408,390037,256534,229706,7684,
                   2035,2836925,350279,255278,537031,1654,50488,
                   10162,290445,549321,935066,302686,56031,
                   596060,370867,85411,253108,323008,5529824])

cc_arr_sm = cc_arr/1000 # rimpicciolisce a dimensione dei punti (?)
color_arr= np.random.rand(26)

# Se faccio questi sotto vengono aggiunti ad una figura aggiuntiva, non al mio scatterplot
# questo perche' ho provato ad usare la strada per cui prima faccio la figura, aggiungo gli assi
# e il disegno viene con un metodo!
#plt.title('Mortalita per 100k vs. Casi confermati')
#plt.xlabel('Mortalita per 100k')
#plt.ylabel('Casi confermati')
#plt.scatter(dr_arr, test_arr, s=cc_arr_sm, c=color_arr,alpha=0.5 )
#plt.figure(figsize=(8,5))


fig_13 = plt.figure(figsize=(8,5))
axes_13 = fig_13.add_axes([0.1,0.1,0.9,0.9])
axes_13.set_xlabel('Mortalita per 100k')
axes_13.set_ylabel('Casi confermati')
axes_13.set_title('Mortalita per 100k vs. Casi confermati')

axes_13.scatter(dr_arr,       # valori sull'asse delle x
                test_arr,     # valori sull'asse delle y
                s=cc_arr_sm,  # valori che indicano la dimensione dei punti
                c=color_arr,  # colori di ogni punto
                alpha=0.2 );  # trasparenza 1 = no trasparenza, 0 = completamente trasparente

png

3D

  • from mpl_toolkits import mplot3d abbiamo bisogno di importare questo modulo
  • projection='3d' quando si costruisce la figura si aggiunge questo parametro
  • fig_9 = plt.figure(figsize=(8,5), dpi=100) dpi=100 stranamente sembra avere un effetto sulla dimensione della figura, mentre sembra non prendere il parametro figsize! Probabilmente questo e’ dovuto al fatto che con %matplotlib inline mi mette le figure come dei png, cambiando il numero di punti questo cambia la dimensione dell’immagine a schermo. Per esempio dpi=100 e’ circa un terzo della figura con dpi=300
  • scatter3D la funzione per uno scatterplot 3D
  • c= z_3 se uso questo parametro per i colori, allora quelli piu’ in alto (asse z) avranno una sfumatura differente da quelli in basso

Scatter3D

from mpl_toolkits import mplot3d

fig_9 = plt.figure(figsize=(6,5), dpi=100)
axes_9 = fig_9.add_axes([0.1,0.1,0.9,0.9], projection='3d')   # mette degli assi 3D

z_3 = 40 *np.random.random(100)            # random:  sample dalla [0,1) uniforme
x_3 = np.sin(z_3) * np.random.randn(100)   # randn
y_3 = np.cos(z_3) * np.random.randn(100)   # randn: sample dalla N(0,1)

#axes_9.scatter3D(x_3,y_3,z_3, cmap='Blues');
axes_9.scatter3D(x_3,y_3,z_3, c=z_3, cmap='Blues');


png

Contour3D

In questo caso ho bisogno di una funzione z =z(x,y) questo perche’ lui deve poter sapere la altezza in ogni punto.

  • per costruire una griglia rettangolare devo usare np.meshgrid: x_4, y_4 = np.meshgrid(x_4, y_4) occhio che se non metto questo comando mi dice che c’e’ un errore!? Il motivo e’ semplice. meshgrid prende in ingresso due array 1 dimensionali e restituisce due array 2 dimensionali. In pratica ha fatto un prodotto cartesizano per ognuno dei punti del primo array creando una coppia con quelli del secondo array (e viceversa per il secondo array). Questo perche’ contour3D si aspetta delle matrici per le x e le y e anche le z, in quanto per ogni x e y c’e’uno z. Per capire meglio fai fare print(x_4) prima e dopo meshgrid e vedi la differenza.

  • Angolo di vista, per cambiare: axes_9.view_init(45, 55). questo sposta l’angolo di vista di 45 gradi e lo ruota di 55
  • il 4to parametro indica il numero di linee. In pratica quante fette parallele al piano xy che vengono visualizzate, se metto 80 sono tante, se metto 20 sono poche
fig_9 = plt.figure(figsize=(6,5), dpi=100)
axes_9 = fig_9.add_axes([0.1,0.1,0.9,0.9], projection='3d')

def get_z (x,y):
    return np.sin(np.sqrt(x**2+y**2))

x_4 = np.linspace(-6,6,30)
y_4 = np.linspace(-6,6,30)

#print(x_4)   
x_4, y_4  = np.meshgrid(x_4, y_4)
#print(x_4)


z_4 = get_z(x_4, y_4)

axes_9.set_xlabel('x')
axes_9.set_ylabel('y')
axes_9.set_zlabel('z')

axes_9.view_init(35, 30)  # angolo di visione, angolo di rotazione
axes_9.contour3D(x_4,y_4,z_4, 20, cmap='Blues');

png

WireFrame e surface

In questo caso vengono connessi tutti i punti da un segmento. -plot_wireframe(x_4,y_4,z_4, cmap='Blues') in questo caso non devo passare il numero di tagli paralleli all’asse xy, quindi non ha il 4to parametro.

  • edgecolor ='none' non colora i segmenti di collegamento (il wireframe)
fig_9 = plt.figure(figsize=(6,5), dpi=100)
axes_9 = fig_9.add_axes([0.1,0.1,0.9,0.9], projection='3d')
axes_9.view_init(35, 30)  # angolo di visione, angolo di rotazione
#axes_9.plot_wireframe(x_4,y_4,z_4, cmap='Blues');

axes_9.plot_surface(x_4,y_4,z_4, rstride=1, cstride=1,  cmap='Blues', edgecolor='r');

png

Finance Module

per installare ho fatto:

  • anaconda prompt
  • pip install mpl_finance
  • pip install –upgrade mplfinance # upgrade

questo modulo fa vedere le candele giapponesi ecc.

  • posso cambiare il nome dell’index: goog_df.index.name='Date' a questo punto l’index non si chiama piu’ index ma Date! mi pare di capire che questo sia necessario perche’ la libreria prenda correttamente il dataframe.

Candele giapponesi

  • Attento se prendi tante date, non riesci a vedere le candele! devono essere poche per essere visibili.

trendlines

possiamo mettere automaticamente delle medie mobili con il parametro: -type='ohlc', mav=4 # che significa che mette Open High Low Close e la media mobile basata sui precedenti 4 punti,nota che possiamo tenere come type ‘candle’ (ma si vede meno bene)

  • altri tipi di medie mobili. mav=(3,5,7) e’ bene usare dispari, quindi fa vedere 3 medie mobili basate sui 3, 5 e 7 gg precedenti
  • il parametro volume=True va vedere i volumi giornalieri
  • mostrare non-tading days: show_nontrading=True

parse_dates

  • parse_dates=true vuol dire che non prende le date come delle semplici stringhe ma le legge come date, infatti ora sono in formato Timestamp
import mplfinance as mpf

goog_df = pd.read_csv('GOOG.csv', index_col = 0, parse_dates=True)
#type(goog_df.index[0])
goog_df.index.name='Date'

#goog_df = pd.read_csv('GOOG.csv')
goog_df.head(3)
Open High Low Close Adj Close Volume
Date
2019-08-21 1193.150024 1199.000000 1187.430054 1191.250000 1191.250000 740700
2019-08-22 1194.069946 1198.011963 1178.579956 1189.530029 1189.530029 947500
2019-08-23 1181.989990 1194.079956 1147.750000 1151.290039 1151.290039 1687000
mask = (   ( pd.to_datetime(goog_df.index) >= pd.to_datetime('5/20/2020')) 
         & ( pd.to_datetime(goog_df.index) <= pd.to_datetime('8/19/2020')) )

new = goog_df.loc[mask]   # 
#mpf.plot(new, type='line')     # normali linee
#mpf.plot(new, type='candle')   # candele giapponesi
#mpf.plot(new, type='ohlc', mav=4)   # open high low close + moving average
mpf.plot(new, type='ohlc', mav=(3,5,7), volume=True, show_nontrading=True)   # open high low close + moving average

png

Heatmap

ho un array 2 dimensionale e voglio mostrarlo con dei colori invece che dei numeri.

  • symptoms sono i 4 tipi di malattia a cui si riferiscono i dati (dyspnea = short of breath)
  • dates sono i giorni in cui sono state fatte le osservazioni (sono 9 giorni)
  • symp_per sono il numero di pazienti per giorno per malattia e’ un array 4x9

Nota: pensavo che la heatmap di default mettesse delle righe bianche in mezzo alle caselle risultando molto poco chiara! in realta’ e’ una delle opzioni lasciate dal finance module!!!! (se faccio girare prima la casella sotto le righe bianche in mezzo non ci sono!)

  • Per la heatmap si deve usare subplots() (non figure)
  • Cosa fa il comando? prende la matrice che ha 0,3 righe, e 0,8 colonne. Per ognuna delle righe e delle colonne scrive un colore associato al numero dell’ingresso dell’array da disegnare.
symptoms = ["Coronavirus","Influenza","Pneumonia","Dyspnea"]
dates = ["Jun28","Jul05","Jul12","Jul19","Jul26","Aug02","Aug09","Aug16","Aug21"]
symp_per = np.array([[5.2, 5.5, 5.7, 5.6, 5.3, 5.1, 5.0, 4.9, 5.3],
                    [3.5, 4.0, 4.3, 3.9, 3.5, 3.2, 2.7, 2.2, 2.0],
                    [1.8, 2.2, 2.3, 2.2, 2.1, 1.9, 1.7, 1.4, 1.3],
                    [1.0, 1.1, 1.1, 1.0, 0.9, 0.8, 0.8, 0.8, 0.7]])
fig_10 , axes_10 = plt.subplots()
im= axes_10.imshow(symp_per, cmap='Wistia')

png

tics

non chiaro perche’ all’inizio metta un np.arange, dato che abbiamo gia’ un array con dates e symptoms:

  • ok: axes_10.set_xtics(np.arange(len(dates)) qui definisce la distanza (posizione) che devono avere i tics sulla mappa.
  • axes_10.set_xticlabels(dates) questo definisce cosa ci deve essere nei ticks
  • occhio che ticks ha la k
  • occhio i ticks vanno assegnati DOPO avere definito la figura e l’axes
  • giro i ticks di 45 gradi! plt.setp(axes_10.get_xticklabels(), rotation=45, ha='right', rotation_mode='anchor') (non chiaro l’anchor cosa faccia)
fig_10 , axes_10 = plt.subplots()
im= axes_10.imshow(symp_per, cmap='Wistia')

axes_10.set_xticks(np.arange(len(dates)))       # posizione tics sull'asse x
axes_10.set_yticks(np.arange(len(symptoms)))    # posizione tics sull'asse y
                  
axes_10.set_xticklabels(dates)                 # cosa viene mostrato ad ogni tic dell'asse x 
axes_10.set_yticklabels(symptoms)                 # cosa viene mostrato ad ogni tic dell'asse x 
                  
plt.setp(axes_10.get_xticklabels(), rotation=45, ha='right');                  

png

Numeri nelle caselle

metto qui anche i numeri dentro le caselle. Nota che usa un costrutto che non ho mai usato prima, chiama un metodo dell’axes dentro una funzione di matplotlib.

-plt.setp(axes_10.get_xticklabels(), rotation=45, ha='right');

  • chiama
fig_10 , axes_10 = plt.subplots()
im= axes_10.imshow(symp_per, cmap='Wistia')

axes_10.set_xticks(np.arange(len(dates)))       # posizione tics sull'asse x
axes_10.set_yticks(np.arange(len(symptoms)))    # posizione tics sull'asse y
                  
axes_10.set_xticklabels(dates)                 # cosa viene mostrato ad ogni tic dell'asse x 
axes_10.set_yticklabels(symptoms)                 # cosa viene mostrato ad ogni tic dell'asse x 
                  
plt.setp(axes_10.get_xticklabels(), rotation=45, ha='right'); 

for i in range(len(symptoms)):
    for j in range(len(dates)):
        text = axes_10.text(j,i, symp_per[i,j], ha='center', va='center', color='k', fontweight='bold')


png

Riempire le aree tra curve

ci sono ottimi esempi al sito di matplotlib:

https://matplotlib.org/3.1.1/gallery/lines_bars_and_markers/fill_between_demo.html

il metodo degli assi fill_between() permette di riempire quello che c’e’ tra una curva e l’altra.

x = np.arange(0.0, 2, 0.01)           # le x
y1 = np.sin(2 * np.pi * x)            # y1 = la funzione seno
y2 = 1.2 * np.sin(4 * np.pi * x)      # y2 = funzione seno piu' larga e con maggiore frequenza
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True)  

ax1.fill_between(x, 0, y1)          # riempie tra 0 e y1
ax1.set_ylabel('TRA y1 e 0')

ax2.fill_between(x, y1, 1)          # riempie tra y1 e 1 (quello che c'e' sopra y1) 
ax2.set_ylabel('TRA y1 e 1')  

ax3.fill_between(x, y1, y2)         # quello che c'e' TRA y1 e sotto y2
ax3.set_ylabel('TRA y1 e y2')
ax3.set_xlabel('x')
Text(0.5, 0, 'x')

png

si possono mettere ulteriori condizioni per dare dei colori diversi tra le curve. In particolare si aggiungono dei parametri logici.

fig, (ax, ax1) = plt.subplots(2, 1, sharex=True)       # costruisce subplots
ax.plot(x, y1, x, y2, color='black')                   # disegna le 2 funzioni 
ax.fill_between(x, y1, y2, where=y2 >= y1, facecolor='green', interpolate=True)
ax.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red', interpolate=True)
ax.set_title('fill between where')

# Test support for masked arrays.
y2 = np.ma.masked_greater(y2, 1.0)
ax1.plot(x, y1, x, y2, color='black')
ax1.fill_between(x, y1, y2, where=y2 >= y1,
                 facecolor='green', interpolate=True)
ax1.fill_between(x, y1, y2, where=y2 <= y1,
                 facecolor='red', interpolate=True)
ax1.set_title('Now regions with y2>1 are masked')
Text(0.5, 1.0, 'Now regions with y2>1 are masked')

png

Ticks

Al comando ticks possono essere passati degli argomenti per specificare:

  • rotation = 45 ruota di 45 gradi
  • se il primo ingresso e’ un np.array allora quelli sono i ticks (le posizioni)
  • se il secondo ingresso e’ una tupla, allora alle varie posizioni dei ticks vengono messi i valori della tupla
  • fontsize=24 viene passato

come al solito puoi passare piu’ di un parametro basta che sia separato dalla virgola!

plt.plot(x_1,y_1)
#plt.xticks(np.linspace(0,5,100))
#plt.xticks(np.arange(15))
#plt.xticks(np.arange(5), ('Tom', 'Dick', 'Harry', 'Sally', 'Sue'))
#plt.grid(False, color='r', dashes=(0,2,1,2)) 
plt.grid(False) 
#plt.grid(b=None)
degrees = 45
plt.xticks(rotation=degrees)           # Rotazione dei ticks 
mioArray= np.array([1,2,3,4,8])
#plt.xticks(np.linspace(0,5,5), ('Tom', 'Dick', 'Harry', 'Sally', 'Sue'))
plt.grid(True)                         # presenza della grid 
plt.xticks(fontsize=24)                # GRANDEZZA FONT
plt.xticks(mioArray, ('Gino', 'Pino', 'Mino', 'Tino', 'Asdrubale'));

png

Animazioni

Testo di riferimento: https://riptutorial.com/Download/matplotlib-it.pdf

Lo ho scaricato ed e’ nella dir.

  • Bisogna importare anche la parte del package che fa animazioni.
  • Bisogna usare il metodo set_data() che assegna i valori delle x e y di un grafico
%matplotlib notebook
import matplotlib.animation as animation
TWOPI = 2*np.pi
fig, ax = plt.subplots()                    # costruiamo una figura e un array di assi
t = np.arange(0.0, TWOPI, 0.001)            # t =array di posizioni 
s = np.sin(t)                               # y = sin(t) 
l = plt.plot(t, s)                          # grafico  
ax = plt.axis([0,TWOPI,-1,1])               # assi

redDot, = plt.plot([0], [np.sin(0)], 'ro')  # l'oggetto "redDot" disegna il punto rosso, all'inizio e' in zero

def animate(i):                             # questa funzione modifica i parametri del punto rosso
 redDot.set_data(i, np.sin(i))              # quindi il resto del grafico resta invariato!  
 return redDot,

# create animation using the animate() function
myAnimation = animation.FuncAnimation(fig, animate, frames=np.arange(0.0, TWOPI, 0.01), \
 interval=1, blit=True, repeat=True)
<IPython.core.display.Javascript object>

Mio test di animazione

vorrei fare estendere la funzione seno, in modo che ad ogni frame sia moltiplicata per una diversa ampiezza. Attenzione: ho provato a farlo girare molte volte e non andava. Ho resettato il kernel e ora sembra fungere. Mi viene il dubbio che il problema fosse connesso a qualche cella che avevo lasciato attiva.

  • Curiosamente se metto i limiti degli assi il grafico non appare! Errore Ax e’ un array di assi!
  • interval=1 rallenta l’esecuzione del programma
  • frames sono tutti i vari prarametri che andranno a definire i frame

possiamo ingrandire o diminuire la dimensione dei limiti: https://stackoverflow.com/questions/53423868/matplotlib-animation-how-to-dynamically-extend-x-limits

TWOPI = 2*np.pi
#fig, ax = plt.subplots()                    # costruiamo una figura e un array di assi

fig = plt.figure()
ax = fig.add_subplot(111, autoscale_on=False, xlim=(0, 6.29), ylim=(-2, 2))


#ax = plt.axis([0,TWOPI,-1,1])              # ATTENTO assi QUESTO BLOCCA set_xlim
#ax.set_xlim([0,TWOPI])                     # ERRORE ax non e' un asse ma una tupla di assi!  
#ax.set_ylim([-1,1])                        # ERRORE    

t = np.arange(0.0, TWOPI, 0.001)            # t =array di posizioni 
s = np.sin(t)  
# y = sin(t) 
plt.grid(False)

new = plt.plot(t, t)                        # bisettrice
second = plt.plot(t,s/2)
curva, = plt.plot(t, s)                     # grafico  
#ax = plt.axes(xlim=(0, 10), ylim=(-1, 1))


def animate(A):                             # questa funzione modifica i parametri del punto rosso
 curva.set_ydata(A *np.sin(t))              # quindi il resto del grafico resta invariato!  
 #print(A*np.sin(t))
 return curva,

frames1 = np.arange(0.0,1.0,0.001)
frames2 = np.arange(1.0,0.0,-0.001)
frames = np.concatenate((frames1, frames2), axis=None)

# create animation using the animate() function
#myAnimation = animation.FuncAnimation(fig, animate, frames = np.arange(0.0, 1.0, 0.001), \
# interval=10, blit=True, repeat=True)

myAnimation = animation.FuncAnimation(fig, animate, frames = frames, \
 interval=1, blit=True, repeat=True)
<IPython.core.display.Javascript object>

Slider interattivo

possiamo modificare la figura tramite uno slider interattivo! In questo caso non uso la funzione animate, perche’ la modifica viene fatta in base a cosa tocco sullo slider.

from matplotlib.widgets import Slider
TWOPI = 2*np.pi
fig, ax = plt.subplots()

A0 = .5                                       # valore iniziale ampiezza 
t = np.arange(0.0, TWOPI, 0.001)              # x del grafico 
s = A0*np.sin(t)                              # y del grafico  (iniziale)

l, = plt.plot(t, s, lw=2)                     # grafico (da capire la virgola)

ax = plt.axis([0,TWOPI,-1,1])                 # assi (che non verranno toccate) ??? 
axamp = plt.axes([0.25, .03, 0.50, 0.02])     # non chiaro axIs e axEs

# Slider
samp = Slider(axamp, 'Amp', 0, 1, valinit=A0) # SLIDER interattivo, si chiama  "samp"

def update(val):
 # amp is the current value of the slider
 amp = samp.val                               # valore corrente dello slider
 # update curve
 l.set_ydata(amp*np.sin(t))                   # fai update delle y della curva  
 # redraw canvas while idle
 fig.canvas.draw_idle()                       

samp.on_changed(update)                       # ridisegna la figura se muoviamo lo slider

#plt.show()

<IPython.core.display.Javascript object>

0

Foto

Vediamo come mostrare una immagine. Si passa un array 2D e questo viene convertito automaticamente, assegnando ai valori un colore. Per esempio:

immagine = np.array([ [1,0,0,0,1,0,0,0,1],
                      [0,0,0,0,1,0,0,0,0],
                      [0,0,0,0,1,0,0,0,0],
                      [0,0,0,0,1,0,0,0,0],
                      [0,0,0,0,1,0,0,0,0],
                      [1,0,0,0,1,0,0,0,1]])

plt.imshow(immagine)
<matplotlib.image.AxesImage at 0x2de6a38e640>

png

Unpacking

questo non e’ strettamente connesso con matplotlib….

numbers = [1, 2, 3, 4, 5, 6]
first, *rest = numbers       # multiple assignment
print(rest)
print(first)

d = dict(a=5,b=2,c=4)

[2, 3, 4, 5, 6]
1

enumerate()

for o,_ in enumerate(d):
    print(o)                # stampa l'ordine degli oggetti
0
1
2
for _, o in enumerate(d):
    print(o)                # stampa le chiavi del dizionario
a
b
c
for _, o in enumerate(d):
    print(d[o])              # stampa i valori del dizionario
5
2
4
for o in enumerate(d):
    print(o)              # stampa le NUOVE coppie chiave-chiave vecchia costruite da enumerate()
(0, 'a')
(1, 'b')
(2, 'c')


Top