HTML CSS JAVASCRIPT SQL MYSQL PYTHON JAVA PHP C C++ C# PACKET TRACER CYBERSECURITY REACT TYPESCRIPT NODE.JS GIT & GITHUB DATA SCIENCE BOOTSTRAP GO KOTLIN JQUERY DJANGO VUE ANGULAR MONGODB POSTGRESQL SASS NUMPY PANDAS SCIPY DSA RUST SWIFT BASHXMLW3.CSSANGULARJSAIAWSPROGRAMMAZIONEEXCEL WORD POWERPOINT
Corso gratuito

Corso SciPy in italiano

La libreria Python per il calcolo scientifico e tecnico: ottimizzazione, matrici sparse, algoritmi su grafi, dati spaziali, interpolazione e test statistici. Con esempi pratici ed esercizi.

Introduzione a SciPy

SciPy (Scientific Python) è una libreria open-source per il calcolo scientifico e tecnico. Costruita sopra NumPy, aggiunge moduli specializzati per ottimizzazione, algebra lineare, integrazione, interpolazione, statistica, elaborazione di segnali e molto altro.

Se NumPy fornisce gli array e le operazioni di base, SciPy fornisce gli algoritmi scientifici pronti all'uso che ci lavorano sopra.

SottomoduloA cosa serve
scipy.constantsCostanti fisiche e matematiche
scipy.optimizeTrovare radici e minimi di funzioni
scipy.sparseMatrici sparse (efficienti in memoria)
scipy.sparse.csgraphAlgoritmi su grafi
scipy.spatialDistanze, triangolazioni, KD-Tree
scipy.interpolateInterpolazione di dati
scipy.statsDistribuzioni e test statistici
scipy.ioLettura/scrittura formati (Matlab, ...)
scipy.linalgAlgebra lineare avanzata
💡 SciPy è scritto in gran parte in linguaggi compilati (C, C++, Fortran), quindi gli algoritmi sono velocissimi pur essendo richiamabili da Python.

Installazione e importazione

Installazione
# Nel terminale
pip install scipy

# In un notebook Jupyter
!pip install scipy

# Spesso insieme a NumPy (richiesto)
pip install numpy scipy
Importazione e versione
import scipy
print(scipy.__version__)   # es. 1.13.0

# I sottomoduli vanno importati esplicitamente
from scipy import constants, optimize, stats
import numpy as np

print(constants.pi)        # 3.141592653589793
⚠️ Importare solo import scipy non basta: i sottomoduli (come scipy.optimize) vanno importati esplicitamente con from scipy import optimize.

Costanti SciPy

Il modulo scipy.constants offre un grande catalogo di costanti fisiche e matematiche, oltre a fattori di conversione tra unità di misura.

Costanti principali
from scipy import constants

print(constants.pi)          # 3.141592653589793
print(constants.golden)      # 1.618033988749895 (sezione aurea)
print(constants.c)           # 299792458.0 (velocità luce m/s)
print(constants.h)           # costante di Planck
print(constants.G)           # costante gravitazionale
print(constants.e)           # carica elementare
print(constants.Avogadro)    # 6.022e23
Fattori di conversione (unità)
from scipy import constants

# Tempo (in secondi)
print(constants.minute)   # 60.0
print(constants.hour)     # 3600.0
print(constants.day)      # 86400.0

# Lunghezza (in metri)
print(constants.inch)     # 0.0254
print(constants.mile)     # 1609.344
print(constants.kilo)     # 1000.0

# Massa (in kg)
print(constants.gram)     # 0.001
print(constants.pound)    # 0.45359237

# Categorie disponibili
print(constants.unit("speed of light in vacuum"))
CategoriaEsempi
Metricokilo, centi, milli
Tempominute, hour, year
Lunghezzainch, foot, mile
Massagram, pound, ounce
Pressioneatm, bar, mmHg

Ottimizzatori (optimize)

Il modulo scipy.optimize offre algoritmi per trovare le radici di un'equazione e per minimizzare funzioni — operazioni centrali nel machine learning e nell'ingegneria.

Trovare le radici di un'equazione

root — risolvere f(x) = 0
from scipy.optimize import root
from math import cos

# Risolvi  x + cos(x) = 0
def equazione(x):
    return x + cos(x)

soluzione = root(equazione, 0)   # 0 = stima iniziale
print(soluzione.x)        # [-0.73908513]
print(soluzione.fun)      # ~0  (valore di f nella soluzione)

Minimizzare una funzione

minimize — trovare il minimo
from scipy.optimize import minimize

# Minimizza  f(x) = x^2 + x + 2
def f(x):
    return x**2 + x + 2

ris = minimize(f, x0=0, method="BFGS")
print(ris.x)         # [-0.5]  → punto di minimo
print(ris.fun)       # 1.75    → valore minimo

# Funzione a più variabili: f(x,y) = (x-1)^2 + (y-2.5)^2
def g(v):
    x, y = v
    return (x-1)**2 + (y-2.5)**2

ris2 = minimize(g, x0=[0, 0])
print(ris2.x)        # [1.  2.5]
MetodoQuando usarlo
BFGSFunzioni lisce, derivabili (default)
Nelder-MeadSenza derivate, robusto
PowellSenza derivate, direzioni coniugate
L-BFGS-BCon vincoli (bounds) sulle variabili

Dati sparsi (sparse)

Una matrice sparsa è una matrice in cui la maggior parte degli elementi è zero. Memorizzare solo gli elementi non-zero risparmia enormi quantità di memoria — fondamentale in NLP, sistemi di raccomandazione e reti.

Creare matrici sparse
import numpy as np
from scipy.sparse import csr_matrix

# Array con molti zeri
arr = np.array([0, 0, 0, 1, 0, 0, 2, 0, 0, 3])

# CSR = Compressed Sparse Row
sparse = csr_matrix(arr)
print(sparse)
#   (0, 3)    1
#   (0, 6)    2
#   (0, 9)    3

# Solo i valori non-zero memorizzati
print(sparse.data)          # [1 2 3]
print(sparse.count_nonzero())  # 3
Operazioni su matrici sparse
import numpy as np
from scipy.sparse import csr_matrix

m = np.array([[0, 0, 1],
              [1, 0, 0],
              [0, 2, 0]])
s = csr_matrix(m)

# Elimina gli zeri duplicati / memorizzati inutilmente
s.eliminate_zeros()

# Converti di nuovo in array denso
print(s.toarray())

# CSC = Compressed Sparse Column (efficiente per colonne)
from scipy.sparse import csc_matrix
sc = csc_matrix(m)

# Somma, prodotto e altre operazioni funzionano come NumPy
print(s.sum())   # 4
FormatoOttimizzato per
csr_matrixOperazioni per riga, prodotti matrice-vettore
csc_matrixOperazioni per colonna
coo_matrixCostruzione rapida da coordinate
lil_matrixModifiche incrementali

Grafi (csgraph)

Il modulo scipy.sparse.csgraph implementa algoritmi classici sui grafi, rappresentati come matrici di adiacenza sparse.

Componenti connesse
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import connected_components

# Matrice di adiacenza (grafo non orientato)
arr = np.array([
    [0, 1, 2],
    [1, 0, 0],
    [2, 0, 0]
])
grafo = csr_matrix(arr)

n, etichette = connected_components(grafo)
print(n)          # numero di componenti connesse
print(etichette)  # a quale componente appartiene ogni nodo
Cammino minimo (Dijkstra)
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import dijkstra, floyd_warshall

# Grafo pesato
arr = np.array([
    [0, 1, 2],
    [1, 0, 0],
    [2, 0, 0]
])
grafo = csr_matrix(arr)

# Dijkstra dal nodo 0
dist, predecessori = dijkstra(
    grafo, return_predecessors=True, indices=0
)
print(dist)   # distanza minima dal nodo 0 a ogni nodo

# Floyd-Warshall: distanze tra tutte le coppie
print(floyd_warshall(grafo, directed=False))
AlgoritmoFunzione
Componenti connesseconnected_components
Cammino minimo (sorgente singola)dijkstra, bellman_ford
Cammini tra tutte le coppiefloyd_warshall
Albero ricoprente minimominimum_spanning_tree

Dati spaziali (spatial)

Il modulo scipy.spatial gestisce dati nello spazio: calcolo di distanze, triangolazioni, inviluppi convessi e ricerche di vicinato efficienti con i KD-Tree.

Distanze tra punti
from scipy.spatial.distance import euclidean, cityblock, cosine

p1 = (1, 0, 0)
p2 = (10, 2, 7)

# Distanza euclidea (in linea d'aria)
print(euclidean(p1, p2))   # 11.575...

# Distanza Manhattan (a blocchi di città)
print(cityblock(p1, p2))   # 18

# Distanza coseno (similarità tra vettori)
print(cosine([1, 0], [0, 1]))   # 1.0 (ortogonali)
print(cosine([1, 1], [1, 1]))   # 0.0 (identici)
Triangolazione e Convex Hull
import numpy as np
from scipy.spatial import Delaunay, ConvexHull

punti = np.array([
    [0, 0], [0, 1], [1, 0],
    [1, 1], [0.5, 0.5]
])

# Triangolazione di Delaunay
tri = Delaunay(punti)
print(tri.simplices)   # indici dei triangoli

# Inviluppo convesso (perimetro esterno)
hull = ConvexHull(punti)
print(hull.vertices)   # punti sul bordo esterno
print(hull.area)       # perimetro
print(hull.volume)     # area racchiusa
KD-Tree: ricerca del vicino più prossimo
import numpy as np
from scipy.spatial import KDTree

punti = np.array([[1, 1], [2, 2], [3, 3], [5, 5]])
tree = KDTree(punti)

# Trova il punto più vicino a (2.1, 2.1)
dist, idx = tree.query([2.1, 2.1])
print(f"Vicino: {punti[idx]}, distanza: {dist:.3f}")

# I 2 vicini più prossimi
dist, idx = tree.query([2.1, 2.1], k=2)
print(punti[idx])

Array Matlab (io)

SciPy può leggere e scrivere file in formato Matlab (.mat), utile quando si collabora con chi usa Matlab o si riutilizzano dataset scientifici esistenti.

Salvare e caricare file .mat
import numpy as np
from scipy import io

# Dati da salvare
arr = np.arange(10)

# Salva in formato Matlab
io.savemat("dati.mat", {"vettore": arr})

# Carica un file .mat
contenuto = io.loadmat("dati.mat")
print(contenuto["vettore"])   # [[0 1 2 3 4 5 6 7 8 9]]

# I dati Matlab sono sempre 2D: usa squeeze per appiattire
print(contenuto["vettore"].squeeze())  # [0 1 ... 9]
💡 Matlab memorizza tutto come matrici 2D, quindi un vettore 1D salvato e ricaricato torna come matrice riga (1, n). Usa .squeeze() o squeeze_me=True in loadmat per ottenere di nuovo un array 1D.

Interpolazione (interpolate)

L'interpolazione stima nuovi valori "in mezzo" a punti dati noti. È usata per ricostruire curve, riempire dati mancanti o aumentare la risoluzione di un campionamento.

Interpolazione 1D
import numpy as np
from scipy.interpolate import interp1d

# Punti noti
x = np.arange(10)
y = 2 * x + 1          # retta: y = 2x + 1

# Crea la funzione interpolante
f = interp1d(x, y)

# Stima valori intermedi
print(f(2.5))          # 6.0
print(f([1.5, 4.5, 8.2]))  # valori interpolati

# Interpolazione cubica (curva liscia)
f_cubica = interp1d(x, y, kind="cubic")
print(f_cubica(2.5))
Interpolazione con spline e dati rumorosi
import numpy as np
from scipy.interpolate import UnivariateSpline

# Dati con un po' di rumore
x = np.linspace(0, 10, 20)
y = np.sin(x) + np.random.normal(0, 0.1, 20)

# Spline che leviga il rumore
spline = UnivariateSpline(x, y, s=1)

# Valuta su una griglia più fitta
x_fine = np.linspace(0, 10, 200)
y_smooth = spline(x_fine)
print(y_smooth[:5])
kind / metodoRisultato
linearSegmenti retti tra i punti (default)
nearestValore del punto più vicino
cubicCurva cubica liscia
UnivariateSplineSpline che leviga dati rumorosi

Test di significatività (stats)

Il modulo scipy.stats è una cassetta degli attrezzi statistica completa: distribuzioni di probabilità, statistica descrittiva e test di ipotesi per verificare se un risultato è statisticamente significativo.

Concetti chiave

  • Ipotesi nulla (H₀): l'ipotesi "non c'è effetto / nessuna differenza".
  • p-value: probabilità di osservare i dati se H₀ è vera. Se p < 0.05 si rifiuta H₀.
T-test (confronto tra due gruppi)
import numpy as np
from scipy import stats

# Due gruppi di misurazioni
gruppo_a = np.array([20, 22, 19, 24, 21, 23, 20])
gruppo_b = np.array([28, 27, 30, 26, 29, 31, 28])

# T-test indipendente
t_stat, p_value = stats.ttest_ind(gruppo_a, gruppo_b)
print(f"t = {t_stat:.3f}")
print(f"p-value = {p_value:.5f}")

if p_value < 0.05:
    print("Differenza SIGNIFICATIVA (rifiuto H0)")
else:
    print("Nessuna differenza significativa")
Statistica descrittiva e normalità
import numpy as np
from scipy import stats

dati = np.array([12, 15, 14, 10, 18, 20, 13, 16, 11, 17])

# Statistiche descrittive
print(stats.describe(dati))
print("Media:", np.mean(dati))
print("Moda:", stats.mode(dati, keepdims=True).mode)
print("Asimmetria:", stats.skew(dati))
print("Curtosi:", stats.kurtosis(dati))

# Test di normalità (Shapiro-Wilk)
stat, p = stats.shapiro(dati)
print(f"Normalità p-value: {p:.4f}")
# p > 0.05 → i dati possono essere normali
TestDomanda a cui risponde
ttest_indDue gruppi hanno medie diverse?
ttest_relMisure appaiate prima/dopo diverse?
f_oneway (ANOVA)Tre o più gruppi differiscono?
chi2_contingencyDue variabili categoriche sono associate?
pearsonrDue variabili sono correlate linearmente?
shapiroI dati seguono una distribuzione normale?

Esercizi pratici

🏋️ Esercizio 1 — Trovare il minimo

Usa scipy.optimize.minimize per trovare il punto di minimo della funzione f(x) = (x - 3)² + 5. Verifica che il minimo sia in x = 3 con valore 5.

Soluzione Esercizio 1
from scipy.optimize import minimize

def f(x):
    return (x - 3)**2 + 5

ris = minimize(f, x0=0)
print(f"Minimo in x = {ris.x[0]:.4f}")   # 3.0000
print(f"Valore minimo = {ris.fun:.4f}")  # 5.0000
🏋️ Esercizio 2 — T-test

Due classi hanno svolto lo stesso esame. Verifica con un t-test se i voti delle due classi sono significativamente diversi (soglia p < 0.05).

Soluzione Esercizio 2
import numpy as np
from scipy import stats

classe_a = np.array([6, 7, 5, 8, 7, 6, 7, 5])
classe_b = np.array([8, 9, 7, 9, 8, 9, 8, 7])

t, p = stats.ttest_ind(classe_a, classe_b)
print(f"p-value = {p:.5f}")

if p < 0.05:
    print("Le due classi differiscono significativamente")
else:
    print("Nessuna differenza significativa")
🏋️ Esercizio 3 — Distanza e vicino più prossimo

Dati 4 città su un piano cartesiano, costruisci un KD-Tree e trova quale città è più vicina al punto (3, 4).

Soluzione Esercizio 3
import numpy as np
from scipy.spatial import KDTree

citta = {"Roma": [0,0], "Milano": [2,5],
         "Napoli": [4,3], "Torino": [1,6]}
nomi = list(citta.keys())
punti = np.array(list(citta.values()))

tree = KDTree(punti)
dist, idx = tree.query([3, 4])

print(f"Città più vicina: {nomi[idx]}")
print(f"Distanza: {dist:.3f}")

E ora?

Complimenti! Hai completato il corso SciPy e ora conosci gli strumenti per affrontare problemi scientifici reali in Python: ottimizzazione, algebra su matrici sparse, algoritmi su grafi, geometria computazionale, interpolazione e test statistici.

Cosa hai imparato:
  • Costanti fisiche e conversioni di unità
  • Ottimizzazione: radici e minimi di funzioni
  • Matrici sparse e algoritmi sui grafi
  • Dati spaziali: distanze, Convex Hull, KD-Tree
  • Interpolazione di dati e spline
  • Test di significatività e statistica inferenziale

Insieme a NumPy e Pandas, SciPy completa il trio fondamentale del calcolo scientifico in Python. Il passo successivo? Mettere tutto in pratica nel corso completo di Data Science.

Vai al corso Data Science → Torna ai Corsi 📅 Prenota una lezione