Tutorial NumPy
Impara NumPy da zero: crea e indicizza array, ridimensiona, esegui il broadcasting, le aggregazioni e l'algebra lineare con esempi Python chiari.
NumPy (Numerical Python) è la libreria fondamentale per il calcolo numerico in Python. Introduce l'ndarray — un array multidimensionale veloce e a tipo fisso — e lo abbina a centinaia di funzioni matematiche che operano su interi array in una sola volta. Praticamente ogni libreria scientifica Python (Pandas, SciPy, Matplotlib, scikit-learn) è costruita su NumPy.
Questo capitolo tratta:
- Cosa è NumPy e perché è più veloce delle semplici liste Python
- Installare NumPy e la convenzione di importazione standard
- Creare array con
np.array,np.zeros,np.ones,np.arangeenp.linspace - Indicizzazione, slicing e boolean masking
- Ridimensionamento e trasposizione
- Broadcasting — operare su array con forme diverse
- Funzioni di aggregazione (
sum,mean,std,min,max) - Matematica elemento per elemento e algebra lineare
- Funzioni di utilità comuni (
sort,unique,where,concatenate)
Cos'è NumPy?
NumPy è una libreria Python open source che fornisce:
- Un potente oggetto array N-dimensionale (
ndarray). - Funzioni matematiche elemento per elemento (ufunc) che si applicano a ogni elemento di un array in codice C compilato anziché in un ciclo Python.
- Algebra lineare, trasformate di Fourier e routine per numeri casuali.
Perché NumPy è più veloce delle liste Python
Una lista Python può contenere elementi di qualsiasi tipo, quindi ogni elemento memorizza un tag di tipo e un puntatore al valore effettivo. Gli array NumPy memorizzano i dati numerici grezzi in un blocco contiguo di memoria — senza puntatori, senza ricerche di tipo. Combinato con cicli C vettorializzati (ufunc), le operazioni su un array NumPy da un milione di elementi sono tipicamente 10–100× più veloci rispetto al codice equivalente con un ciclo for Python.
Installare NumPy
NumPy è incluso nella distribuzione Anaconda. Per installarlo manualmente con pip:
pip install numpyImportare NumPy
La convenzione universale è importare NumPy come np:
import numpy as npOgni esempio in questo capitolo assume che questa importazione sia già presente nell'ambito.
Creare Array
Da una lista Python
Passa qualsiasi lista (o lista di liste) a np.array():
[1 2 3 4 5]
int64
(5,)Un array 2-D (matrice) usa una lista di liste:
[[1 2 3]
[4 5 6]
[7 8 9]]
(3, 3)Scorciatoie per la creazione di array
| Funzione | Cosa crea |
|---|---|
np.zeros((2, 3)) | Array di 0.0 con forma (2, 3) |
np.ones(4, dtype=int) | Array di 1 con forma (4,) |
np.eye(3) | Matrice identità 3×3 |
np.arange(start, stop, step) | Come range() di Python, restituisce un array |
np.linspace(start, stop, n) | n valori equidistanti da start a stop |
import numpy as np
print(np.zeros((2, 3)))
print(np.ones(4, dtype=int))
print(np.arange(0, 10, 2))
print(np.linspace(0, 1, 5))[[0. 0. 0.]
[0. 0. 0.]]
[1 1 1 1]
[0 2 4 6 8]
[0. 0.25 0.5 0.75 1. ]np.linspace è particolarmente utile quando si ha bisogno di un numero preciso di punti — ad esempio, per preparare un asse x per un grafico. Consulta il capitolo Introduzione a Matplotlib per sapere come usarlo insieme alle funzioni di plotting.
Indicizzazione e Slicing
Indicizzazione e slicing 1-D
NumPy usa la stessa sintassi [start:stop:step] delle liste Python, ma supporta anche indici negativi e passi (stride).
import numpy as np
a = np.array([10, 20, 30, 40, 50])
print(a[0]) # first element
print(a[-1]) # last element
print(a[1:4]) # elements at index 1, 2, 3
print(a[::2]) # every other element10
50
[20 30 40]
[10 30 50]Indicizzazione 2-D
Per un array 2-D, usa [riga, colonna]:
import numpy as np
b = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(b[1, 2]) # row 1, col 2 → 6
print(b[0, :]) # first row → [1 2 3]
print(b[:, 1]) # second column → [2 5 8]
print(b[0:2, 1:3]) # sub-matrix6
[1 2 3]
[2 5 8]
[[2 3]
[5 6]]Boolean masking
Passa un array boolean come indice per selezionare solo gli elementi in cui la condizione è True:
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(a[a > 3]) # elements greater than 3
print(a[a % 2 == 0]) # even elements[4 5]
[2 4]Le boolean mask sono il sostituto idiomatico NumPy per le list comprehension filtrate e sono molte volte più veloci su array di grandi dimensioni.
Ridimensionamento e Trasposizione
Ridimensionamento
np.reshape() (o il metodo .reshape()) restituisce una vista dei dati con una nuova forma. Il numero totale di elementi deve rimanere lo stesso.
[[1 2 3]
[4 5 6]]Usa -1 per una dimensione che vuoi che NumPy inferisca automaticamente:
import numpy as np
a = np.arange(12)
print(a.reshape(3, -1)) # 3 rows, NumPy infers 4 columns[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]Trasposizione
.T o np.transpose() scambia gli assi (righe ↔ colonne per gli array 2-D):
[[1 3 5]
[2 4 6]]
(2, 3)Aggiungere e Rimuovere Elementi
Aggiungere elementi
np.append() restituisce un nuovo array piatto — non modifica l'originale in-place (a differenza di list.append).
[1 2 3 4 5 6]Per append ripetuti all'interno di un ciclo, costruire una lista Python e convertirla una volta sola con np.array() alla fine è molto più efficiente che chiamare np.append() ripetutamente.
Rimuovere elementi
np.delete(arr, indices) restituisce un nuovo array con gli indici specificati rimossi:
[1 2 5]Concatenare array
np.concatenate() unisce due o più array lungo un asse esistente:
import numpy as np
a = np.array([1, 2])
b = np.array([3, 4])
print(np.concatenate([a, b]))[1 2 3 4]Broadcasting
Il broadcasting è la regola di NumPy per applicare operazioni tra array di forme diverse — senza copiare i dati. L'esempio classico è aggiungere uno scalare a un array:
import numpy as np
a = np.array([1, 2, 3])
print(a + 10) # 10 is broadcast across all elements[11 12 13]Un caso più potente: aggiungere un array 1-D a ogni riga di un array 2-D:
import numpy as np
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
row = np.array([10, 20, 30])
print(matrix + row)[[11 22 33]
[14 25 36]]NumPy confronta le forme da destra: (2, 3) + (3,) è valido perché le dimensioni finali coincidono; row viene concettualmente esteso a un array (2, 3) senza alcuna allocazione di memoria.
Operazioni Matematiche
Aritmetica elemento per elemento
Tutti gli operatori standard (+, -, *, /, **) funzionano elemento per elemento su array della stessa forma. Le funzioni equivalenti con nome (np.add, np.subtract, np.multiply, np.divide) possono essere utili quando si passano operazioni come argomenti.
[5 7 9]
[ 4 10 18]
[1 4 9]Funzioni matematiche universali (ufunc)
NumPy fornisce versioni vettorializzate di tutte le funzioni matematiche standard:
import numpy as np
a = np.array([0, 1, 4, 9, 16], dtype=float)
print(np.sqrt(a))
print(np.log(np.array([1, np.e, np.e**2]))) # natural log
print(np.sin(np.array([0, np.pi/2, np.pi])))[0. 1. 2. 3. 4.]
[0. 1. 2.]
[ 0.000e+00 1.000e+00 -8.742e-08]Il valore minuscolo vicino a zero per sin(π) è normale arrotondamento in virgola mobile — np.pi è un'approssimazione di π.
Funzioni di Aggregazione
Le funzioni di aggregazione riducono un array (o uno dei suoi assi) a un singolo valore:
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(np.sum(a)) # 15
print(np.mean(a)) # 3.0
print(np.std(a)) # 1.4142135623730951
print(np.min(a)) # 1
print(np.max(a)) # 515
3.0
1.4142135623730951
1
5Per gli array 2-D, passa axis=0 per aggregare lungo le colonne o axis=1 per aggregare lungo le righe:
import numpy as np
m = np.array([[1, 2, 3],
[4, 5, 6]])
print(np.sum(m, axis=0)) # column totals: [5 7 9]
print(np.sum(m, axis=1)) # row totals: [6 15][5 7 9]
[ 6 15]Algebra Lineare
np.dot() di NumPy calcola il prodotto scalare di due vettori 1-D o il prodotto matriciale di due array 2-D. Per la moltiplicazione di matrici, l'operatore @ (Python 3.5+) è la scorciatoia moderna.
import numpy as np
a = np.array([1, 2])
b = np.array([3, 4])
print(np.dot(a, b)) # 1*3 + 2*4 = 11
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B) # matrix product11
[[19 22]
[43 50]]np.linalg contiene operazioni più avanzate:
| Funzione | Scopo |
|---|---|
np.linalg.det(A) | Determinante |
np.linalg.inv(A) | Inversa della matrice |
np.linalg.eig(A) | Autovalori e autovettori |
np.linalg.solve(A, b) | Risolve il sistema lineare A·x = b |
Funzioni di Utilità
Ordinamento
import numpy as np
a = np.array([3, 1, 4, 1, 5, 9, 2, 6])
print(np.sort(a)) # returns a sorted copy
print(np.argsort(a)) # indices that would sort the array[1 1 2 3 4 5 6 9]
[1 3 6 0 2 4 7 5]Valori unici
import numpy as np
a = np.array([1, 2, 2, 3, 3, 3])
print(np.unique(a))[1 2 3]Selezione condizionale con np.where
np.where(condition, x, y) restituisce x dove la condizione è True e y altrove:
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(np.where(a > 2, a, 0))[0 0 3 4 5]NumPy con Matplotlib
NumPy e Matplotlib sono progettati per lavorare insieme. np.linspace genera i valori x; le ufunc di NumPy calcolano y; Matplotlib traccia il risultato:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 200)
plt.plot(x, np.sin(x), label='sin')
plt.plot(x, np.cos(x), label='cos')
plt.legend()
plt.title('Sine and Cosine')
plt.show()Questo esempio richiede che Matplotlib sia installato (pip install matplotlib) e un display o un backend Agg per ambienti headless. Consulta il capitolo Introduzione a Matplotlib per una guida dettagliata.
Cosa Imparare Dopo
- Tutorial SciPy — calcolo scientifico di livello superiore (integrazione, ottimizzazione, elaborazione del segnale) costruito sugli array NumPy.
- Introduzione a Matplotlib — visualizza gli array NumPy come grafici a linee, scatter plot, istogrammi e altro.
- Plotting con Matplotlib — perfeziona il layout delle figure, gli assi e gli stili.