Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
FREEDOM251

Freedom251 › Blog › cdist

Understanding SciPy’s cdist: Shapes, Distance Metrics, and When to Use pdist

By Freedom251 Team · · 6 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

scipy.spatial.distance.cdist computes the distance between every row of one array and every row of a second array. If the first array has mA rows and the second has mB rows, the result is an (mA, mB) matrix whose entry at position (i, j) is the distance between row i of the first array and row j of the second. The default metric is Euclidean.

The function signature and what it expects

The function is called as follows, based on SciPy’s v1.18.0 API reference for cdist:

As an Amazon Associate I earn from qualifying purchases.

scipy.spatial.distance.cdist(XA, XB, metric='euclidean', *, out=None, **kwargs)

Three rules govern every call:

  • Both inputs must be two-dimensional. Each row is one observation and each column is one feature.
  • The column counts must match. If XA.shape[1] differs from XB.shape[1], SciPy raises a ValueError. The number of rows may differ.
  • Inputs are converted to floating point. Integer or Boolean arrays are accepted, but the metric is computed on float values, so interpret Boolean inputs with the metric choice in mind (see below).

A worked shape example

Take two small arrays with two observations in XA and three in XB, each having two features:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import numpy as np
from scipy.spatial.distance import cdist

XA = np.array([[0, 0], [1, 1]])      # shape (2, 2)
XB = np.array([[1, 0], [2, 2], [0, 2]])  # shape (3, 2)

D = cdist(XA, XB, metric="euclidean")
print(D.shape)  # (2, 3)

The output has one row per observation in XA and one column per observation in XB. Working the Euclidean arithmetic by hand gives the following values, rounded to three decimals:

Row in XA Distance to XB[0] = (1, 0) Distance to XB[1] = (2, 2) Distance to XB[2] = (0, 2)
XA[0] = (0, 0) 1.000 2.828 2.000
XA[1] = (1, 1) 1.000 1.414 1.414

Each cell is a single pair comparison, so the matrix size is always the product of the two collection sizes. That property matters for memory, discussed later.

Choosing a distance metric

The metric argument determines what “distance” means. The same two arrays can produce very different matrices under different metrics, so the choice should follow from what each feature represents rather than from the default. The table below lists the common string names SciPy accepts and the situations each one fits. The definitions follow SciPy’s API reference; the table is a selection aid, not a ranking, because no metric is universally correct.

Metric string What it measures Typical use Extra arguments
euclidean (default) Straight-line (L2) distance between feature vectors Ordinary geometric distance in numeric feature space None
cityblock Sum of absolute coordinate differences (Manhattan distance) Grid-like movement; features where axis-by-axis differences should add up None
cosine One minus the cosine similarity; ignores vector magnitude Direction-based comparison, such as text or embedding vectors None
correlation Distance based on the correlation between the two vectors Comparing profiles whose shape matters more than level None
hamming Proportion of positions where the two vectors disagree Discrete or categorical vectors of equal length None
jaccard Disagreement among positions where at least one vector is nonzero Set-like binary features, where shared absences should not count as similarity None
minkowski The general p-norm distance Tuning sensitivity to large versus small differences p; p=2 equals Euclidean
seuclidean Euclidean distance with each feature divided by a standard deviation Features on different scales V, the variance vector
mahalanobis Distance that accounts for covariance between features Correlated features where covariance should shape the distance VI, the inverse covariance matrix

Arguments for metrics that need them

Some metrics accept parameters through **kwargs. For minkowski, the p value sets the norm. For seuclidean, V supplies per-feature variances. For mahalanobis, VI supplies the inverse covariance matrix. If you omit V or VI, SciPy can derive defaults from the stacked inputs. That convenience has a cost: the scale or covariance then reflects only the data you passed in this call. When the analysis needs a fixed reference (for example, a training-set covariance applied to new data), compute V or VI yourself and pass it explicitly.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from scipy.spatial.distance import cdist

# Minkowski with p=3
D3 = cdist(XA, XB, metric="minkowski", p=3)

# Mahalanobis with an explicit inverse covariance matrix
VI = np.linalg.inv(np.cov(np.vstack([XA, XB]).T))
Dm = cdist(XA, XB, metric="mahalanobis", VI=VI)

Match the metric to the data type

Boolean and set metrics such as hamming and jaccard treat each position as a category or presence flag. Numeric metrics such as euclidean and cityblock treat each position as a magnitude. Applying a numeric metric to one-hot or presence/absence data can still run without error, but the distances then answer a different question. Also note that numeric metrics are sensitive to feature scale: a feature measured in thousands will dominate a feature measured in fractions unless you standardize first or use seuclidean.

cdist versus pdist and squareform

SciPy also provides pdist, which computes distances among observations within a single collection. The two functions answer different questions, and choosing between them mainly depends on whether the two sets are the same.

Aspect cdist(XA, XB) pdist(X)
Inputs Two collections One collection
Pairs compared Every row of XA against every row of XB Every unique pair of rows within X
Output Full rectangular matrix, shape (mA, mB) Condensed one-dimensional vector of length m(m-1)/2
Typical question How does each new item compare with each reference item? How far apart are the items in one dataset from each other?

When pdist is the better fit

Use pdist when you need only the unique pairwise distances inside one dataset. It stores each pair once, so for a dataset of m observations it holds about half the values of a full square matrix. Clustering routines and similar workflows often consume this condensed form directly.

Converting with squareform

Use scipy.spatial.distance.squareform to move between the two representations. Passing a condensed vector returns a symmetric square matrix with zeros on the diagonal; passing a square matrix returns the condensed vector of its upper-triangle values.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from scipy.spatial.distance import pdist, squareform, cdist

X = np.array([[0, 0], [1, 1], [2, 0]])

condensed = pdist(X)               # length 3 for m = 3
square = squareform(condensed)     # shape (3, 3)

full = cdist(X, X)                 # shape (3, 3), same values as square

Why cdist(X, X) is not the same as pdist(X)

Passing the same array twice to cdist is valid and yields a square (m, m) matrix. That matrix includes the diagonal, where each observation is compared with itself; for Euclidean distance those entries are zero. Off-diagonal pairs appear twice, once in each direction, so the matrix is symmetric. pdist(X) stores each unique off-diagonal pair once and omits the diagonal. Both carry the same information, but they differ in size and layout, and code that expects one layout will break with the other.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common mistakes and checks

  • Confirm column counts before the call. Check XA.shape[1] == XB.shape[1]; a mismatch raises ValueError.
  • Pass a string name for built-in metrics. Write metric="cityblock", not a hand-written Python function that reproduces it. SciPy’s documentation advises string names because a Python callable is invoked once for every pair, which is slower.
  • Plan for the size of the output. The result holds mA * mB floating-point values. For example, 50,000 rows against 50,000 rows produces 2.5 billion values, roughly 20 GB at 8 bytes each. Batch the rows of XA when collections are large.
  • Standardize or set scale arguments deliberately. Review the meaning of V and VI and where they were derived.
  • Do not expect symmetry from cdist with two different arrays. Only cdist(X, X) yields a symmetric matrix.

Speed and memory notes

The documentation describes the performance trade-off qualitatively, not numerically. Built-in metrics given as strings use SciPy’s optimized implementations, while a Python callable adds per-pair overhead. This article does not report runtime or memory measurements for any metric, so treat the batching guidance above as a memory-planning rule derived from the output shape rather than a benchmark.

Version notes

The API described here matches SciPy’s v1.18.0 reference. Parameter names and available metrics can change between releases, so confirm the version you are running:

import scipy
print(scipy.__version__)

If the printed version differs from 1.18.0, check the cdist page for that release before relying on a specific keyword argument.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

cdistdistance metricsNumPypdistPythonScientific ComputingSciPy

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.