SciPy Spatial Data

scipy.spatial offers fast, correct tools for measuring distances, finding nearest neighbors, and computing geometric shapes like convex hulls from sets of points.

Measuring Distance Between Points

scipy.spatial.distance offers dozens of ready-made distance functions so you don't have to derive the math yourself every time. euclidean gives the familiar straight-line distance you'd measure with a ruler, cityblock (also called Manhattan distance) sums the differences along each axis as if you could only move along a grid, and cosine measures how different two vectors' directions are regardless of their length - handy for comparing things like word embeddings or ratings where magnitude matters less than orientation.

Example

from scipy.spatial import distance

shop = (1, 2)
customer = (4, 6)

print(distance.euclidean(shop, customer))   # straight-line distance
print(distance.cityblock(shop, customer))   # grid/taxicab distance
print(distance.cosine(shop, customer))      # difference in direction, not magnitude

Finding Nearest Neighbors with KDTree

Checking the distance from one query point to every single point in a large dataset - a brute-force search - gets slow once you have thousands or millions of points. A KDTree restructures the points into a tree that recursively splits space in half, so a nearest-neighbor search only has to examine a small fraction of the data instead of all of it. Once built, the same tree can answer many different queries very quickly, which makes it a natural fit for tasks like 'find the closest store to this customer' or 'which sensors are near this location'.

Example

import numpy as np
from scipy.spatial import KDTree

shops = np.array([
    [0, 0],
    [5, 4],
    [3, 1],
    [8, 8],
    [2, 6],
])

tree = KDTree(shops)

# The single closest shop to a customer at (4, 4)
dist, index = tree.query([4, 4])
print(dist, index)

# The 3 closest shops, ordered from nearest to farthest
dists, indices = tree.query([4, 4], k=3)
print(dists, indices)

# Every shop within 5 units of the customer
nearby = tree.query_ball_point([4, 4], r=5)
print(nearby)
  • query(point, k=1) - returns the distance(s) and index/indices of the k closest points
  • query_ball_point(point, r) - returns the indices of every point within radius r
  • query_pairs(r) - returns every pair of points in the tree that are within r of each other

Convex Hulls

A convex hull is the smallest convex shape - the tightest 'rubber band' - that encloses a whole set of points, ignoring any points that sit inside the boundary. scipy.spatial.ConvexHull computes this shape and exposes it through properties like vertices (the indices of the boundary points) and volume. Because the underlying Qhull library was written with arbitrary dimensions in mind, its naming can be surprising in 2-D: volume actually means the enclosed area, and area means the perimeter length.

Example

import numpy as np
from scipy.spatial import ConvexHull

points = np.array([
    [0, 0],
    [0, 4],
    [4, 4],
    [4, 0],
    [2, 2],   # inside the square, so it will not be part of the hull
])

hull = ConvexHull(points)

print(hull.vertices)   # indices of the points forming the boundary
print(hull.area)       # in 2-D this is the perimeter length
print(hull.volume)     # in 2-D this is the enclosed area
Metricdistance.functionTypical Use
EuclideaneuclideanStraight-line distance, the most common default
ManhattancityblockGrid-like movement, e.g. city blocks
CosinecosineSimilarity of direction, common for text/embeddings
HamminghammingFraction of differing positions, categorical data
Note: Older SciPy code often uses cKDTree for speed, but modern versions of KDTree already use the same fast C implementation internally, so there's no longer a reason to reach for cKDTree in new code.

Exercise: SciPy Spatial Data

What type of data does scipy.spatial primarily work with?