HOWTO · NumPy

Calcolare la distanza euclidea in Python

Questo tutorial mostra come calcolare la distanza euclidea in python

In questa pagina

Per due array NumPy che rappresentano punti con lo stesso numero di coordinate, calcola la distanza euclidea con np.linalg.norm(point_a - point_b). La sottrazione crea le differenze tra coordinate e la norma L2 del vettore le riduce a un’unica distanza non negativa.

Comprendere la formula della distanza euclidea

Per i punti (a=(a_1,\ldots,a_n)) e (b=(b_1,\ldots,b_n)), la distanza euclidea è la radice quadrata della somma dei quadrati delle differenze di coordinate:

Formula della distanza euclidea: la radice quadrata della somma dei quadrati delle differenze di coordinate.

In NumPy, np.linalg.norm(a - b) esprime direttamente questa definizione. Con un array delle differenze unidimensionale e senza argomento ord, np.linalg.norm calcola la sua norma 2. Entrambi gli input devono descrivere punti in dimensioni compatibili affinché la sottrazione abbia il significato previsto.

Preparare le coordinate di input

Le posizioni delle coordinate devono descrivere gli stessi assi nello stesso ordine: confronta la prima coordinata di un punto con la prima dell’altro, e così via. Rappresenta un punto come array unidimensionale di forma (coordinates,). Una coppia di array di forma (3,), ad esempio, rappresenta due punti nello stesso sistema di coordinate tridimensionale; non rappresenta tre distanze indipendenti.

Tuple e liste possono essere convertite con np.asarray(values, dtype=float) prima della sottrazione. Il tipo a virgola mobile accetta coordinate intere o decimali ed evita il wraparound degli interi senza segno quando una coordinata è minore della corrispondente. Se gli input sono già array NumPy a virgola mobile adatti, la conversione è superflua. Evita di appiattire dati multidimensionali arbitrari solo per far coincidere le forme, perché ciò può nascondere un errore di struttura dell’input invece di correggerlo.

Gli esempi seguenti sono stati eseguiti con Python 3.14.7, NumPy 2.5.3 e SciPy 1.18.1. Le API mostrate sono interfacce consolidate, ma un’applicazione deve comunque usare versioni compatibili con il proprio ambiente Python supportato. SciPy è facoltativo, a meno che non si usino il metodo SciPy o gli strumenti per distanze a coppie.

Calcolare la distanza tra due punti

Il seguente esempio verificato confronta l’espressione della norma consigliata con la formula esplicita, una formulazione con prodotto scalare, math.dist della libreria standard e scipy.spatial.distance.euclidean di SciPy. Tutti e cinque i calcoli producono lo stesso risultato per questa coppia di punti.

"""Verify equivalent Euclidean-distance APIs for one pair of points."""

import math

import numpy as np
from scipy.spatial import distance

point_a = np.array([1.0, 2.0, 3.0])
point_b = np.array([4.0, 5.0, 6.0])

print(f"np.linalg.norm: {np.linalg.norm(point_a - point_b)}")
print(f"formula: {np.sqrt(np.sum((point_a - point_b) ** 2))}")
delta = point_a - point_b
print(f"dot product: {np.sqrt(np.dot(delta, delta))}")
print(f"math.dist: {math.dist(point_a, point_b)}")
print(f"distance.euclidean: {distance.euclidean(point_a, point_b)}")
np.linalg.norm: 5.196152422706632
formula: 5.196152422706632
dot product: 5.196152422706632
math.dist: 5.196152422706632
distance.euclidean: 5.196152422706632

La formula esplicita usa concettualmente il quadrato elemento per elemento con NumPy, seguito da una somma e una radice quadrata. La forma con esponente nell’esempio mantiene il calcolo completo in un’unica espressione. La variante con prodotto scalare calcola la stessa somma dei quadrati perché np.dot(delta, delta) moltiplica le differenze corrispondenti e le somma.

Usa np.linalg.norm quando i punti sono già array o fanno parte di un calcolo NumPy più ampio. Comunica chiaramente l’operazione vettoriale senza esplicitare la riduzione.

Calcolare distanze per riga con axis=1

Per più punti memorizzati come righe di un array bidimensionale, sottrai un punto di riferimento e imposta axis=1. NumPy trasmette l’array di riferimento sulle righe, mentre axis=1 indica a np.linalg.norm di restituire una norma per riga anziché una norma per l’intera matrice.

"""Verify row-wise distances from several points to one reference point."""

import numpy as np

points = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
reference = np.array([1.0, 2.0, 3.0])

print(np.linalg.norm(points - reference, axis=1))
[0.         5.19615242]

La prima riga coincide con il riferimento, quindi la sua distanza è zero. Il secondo risultato è la distanza calcolata nell’esempio con una coppia. Questo schema copre distanze da uno a molti; per tutte le distanze a coppie tra due raccolte, usa una routine dedicata come scipy.spatial.distance.cdist invece di creare un grande array intermedio trasmesso senza considerare l’uso della memoria.

Scegliere tra NumPy, math.dist e SciPy

Il metodo migliore dipende dal codice circostante, non da un’affermazione universale sulla velocità:

  • Usa np.linalg.norm(a - b) per array NumPy, flussi di lavoro vettorizzati e calcoli per riga con axis.
  • Usa math.dist(a, b) per una coppia di normali iterabili Python di coordinate quando NumPy non è necessario altrove.
  • Usa scipy.spatial.distance.euclidean(a, b) quando SciPy è già una dipendenza o quando il calcolo appartiene al più ampio insieme di strumenti di distanza di SciPy.
  • Usa la formula esplicita della somma dei quadrati o il prodotto scalare per insegnare, verificare o adattare il calcolo sottostante. Non rendono il risultato più euclideo dell’espressione della norma.

Convertire liste con np.asarray(..., dtype=float) è utile prima della sottrazione NumPy perché le liste Python non supportano la sottrazione elemento per elemento. math.dist accetta direttamente iterabili di coordinate della stessa lunghezza, mentre le opzioni NumPy e SciPy richiedono i rispettivi pacchetti installati.

Gestire forme incompatibili e tipi di dati numerici

Due punti individuali devono avere lo stesso numero di coordinate. Forme unidimensionali incompatibili non possono essere trasmesse insieme, quindi NumPy solleva un ValueError prima di poter calcolare una distanza.

"""Capture the diagnostic for points with incompatible dimensions."""

import numpy as np

point_a = np.array([1.0, 2.0])
point_b = np.array([3.0, 4.0, 5.0])

try:
    np.linalg.norm(point_a - point_b)
except ValueError as error:
    print(f"ValueError: {error}".rstrip())
ValueError: operands could not be broadcast together with shapes (2,) (3,)

Controlla le forme prima della sottrazione quando le dimensioni provengono da input utente o dati esterni. Per le distanze per riga, un array di punti di forma (rows, coordinates) è compatibile con un riferimento di forma (coordinates,); un’altra forma può essere trasmessa in modo involontario o fallire.

Converti inoltre le coordinate intere senza segno in un tipo con segno o a virgola mobile prima di sottrarre. La sottrazione senza segno può fare wraparound invece di rappresentare una differenza di coordinate negativa, rendendo errata la norma successiva. Usare array a virgola mobile negli esempi evita questo problema e supporta coordinate non intere.

Per una coppia di punti NumPy con dimensioni uguali, np.linalg.norm(point_a - point_b) è il valore predefinito conciso. Aggiungi axis=1 per le distanze per riga e convalida forme e tipi di dati ogni volta che la struttura dell’input non è già garantita.