HOWTO · NumPy

Python でユークリッド距離を計算する

このチュートリアルでは、Python でユークリッド距離を計算する方法を示します

このページの内容

同じ数の座標を表す 2 つの NumPy 配列なら、np.linalg.norm(point_a - point_b) でユークリッド距離を計算できます。減算で座標差を作り、ベクトルの L2 ノルムで 1 つの非負の距離にします。

ユークリッド距離の公式を理解する

点 (a=(a_1,\ldots,a_n)) と (b=(b_1,\ldots,b_n)) のユークリッド距離は、座標差の二乗和の平方根です。

ユークリッド距離の公式: 座標差の二乗和の平方根。

NumPy では np.linalg.norm(a - b) がこの定義を直接表します。一次元の差分配列で ord を指定しなければ、np.linalg.norm は 2 ノルムを計算します。減算が意図どおりの意味を持つには、両方の入力が互換性のある次元の点を表す必要があります。

入力座標を準備する

座標位置は同じ軸を同じ順序で表さなければなりません。片方の最初の座標はもう片方の最初の座標と比較します。1 点は形状 (coordinates,) の一次元配列で表します。たとえば形状 (3,) の配列 2 つは同じ三次元座標系の 2 点を表し、3 個の独立した距離ではありません。

タプルとリストは減算前に np.asarray(values, dtype=float) で変換できます。浮動小数点型は整数と小数の座標を受け入れ、片方が対応座標より小さいときの符号なし整数のラップアラウンドを防ぎます。既に適切な浮動小数点 NumPy 配列なら変換は不要です。形状を合わせるためだけに任意の多次元データを平坦化すると、入力構造の誤りを隠すことがあります。

以下の例は Python 3.14.7、NumPy 2.5.3、SciPy 1.18.1 で実行しました。示す API は確立されていますが、アプリケーションでは自分の対応 Python 環境と互換性のある版を使う必要があります。SciPy の方法またはペアワイズ距離ツールを使わない限り、SciPy は任意です。

2 点間の距離を計算する

次の検証済み例は、推奨するノルム式を明示的な公式、内積形式、標準ライブラリの math.dist、SciPy の scipy.spatial.distance.euclidean と比較します。この点の組では、5 つの計算すべてが同じ結果を返します。

"""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

明示的な公式は概念上 NumPy による要素ごとの二乗 を使い、続けて合計と 平方根 を求めます。例のべき乗形式は計算全体を一つの式に保ちます。内積形式も、np.dot(delta, delta) が対応する差を掛けて足すため、同じ二乗和を計算します。

点が既に配列である場合や、より大きな NumPy 計算の一部である場合は np.linalg.norm を使います。縮約を展開しなくても、ベクトル演算を明確に示せます。

axis=1 で行ごとの距離を計算する

二次元配列の行に複数の点を格納する場合は、基準点を引いて axis=1 を設定します。NumPy は基準配列を行にブロードキャストし、axis=1np.linalg.norm に行列全体の一つのノルムではなく、行ごとに一つのノルムを返すよう伝えます。

"""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]

最初の行は基準点に等しいため距離はゼロです。2 番目の結果は 1 組の例で得た距離です。このパターンは 1 対多の距離を扱います。二つの集合間の全ペアワイズ距離には、メモリを考えず大きなブロードキャスト中間配列を作る代わりに、scipy.spatial.distance.cdist などの専用ルーチンを使ってください。

NumPy、math.dist、SciPy の使い分け

最適な方法は普遍的な速度の主張ではなく、周囲のコードによって決まります。

  • NumPy 配列、ベクトル化ワークフロー、axis を使う行ごとの計算には np.linalg.norm(a - b) を使います。
  • それ以外で NumPy が不要なら、通常の Python 座標イテラブル 1 組には math.dist(a, b) を使います。
  • SciPy が既に依存関係である場合、または計算が SciPy の距離ツールに属する場合は scipy.spatial.distance.euclidean(a, b) を使います。
  • 基になる計算を教える、確認する、変更するには明示的な二乗和公式または内積を使います。ノルム式より結果がよりユークリッド的になることはありません。

Python のリストは要素ごとの減算をサポートしないため、NumPy の減算前に np.asarray(..., dtype=float) で変換すると便利です。math.dist は同じ長さの座標イテラブルを直接受け入れますが、NumPy と SciPy の選択肢にはそれぞれのパッケージが必要です。

互換性のない形状と数値データ型を扱う

個々の 2 点は同じ数の座標を持つ必要があります。互換性のない一次元形状は一緒にブロードキャストできないため、NumPy は距離を計算する前に ValueError を発生させます。

"""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,)

次元がユーザー入力や外部データから来る場合は、減算前に形状を確認してください。行ごとの距離では、形状 (rows, coordinates) の点配列は形状 (coordinates,) の基準点と互換性があります。別の形状は意図しない方法でブロードキャストされるか、失敗することがあります。

また減算前に、符号なし整数座標を符号付き型または浮動小数点型へキャストしてください。符号なし減算では負の座標差を表す代わりにラップアラウンドし、その後のノルムが不正確になります。例の浮動小数点配列はこの問題を避け、整数以外の座標も扱えます。

同じ次元の NumPy 点の 1 組には、np.linalg.norm(point_a - point_b) が簡潔な既定値です。行ごとの距離には axis=1 を加え、入力構造が既に保証されていない場合は常に形状とデータ型を検証してください。