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 magnitudeFinding 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 areaExercise: SciPy Spatial Data
What type of data does scipy.spatial primarily work with?