Spatial Weights¶
Spatial weights are the core concept of GW models. For each target point \(i\), the distance to every other data point \(j\) is computed via a distance metric, and a kernel function converts the distance into a weight \(w_{ij}\). Larger distance means smaller weight.
Distance Metrics¶
pygwmodel supports the following distance metrics:
Distance Type |
Description |
Python Class |
|---|---|---|
CRS Distance |
Automatic selection based on coordinate reference system: Euclidean for projected coordinates, great-circle for geographic coordinates. |
|
Minkowski Distance |
Generalised distance parameterised by \(p\): \(p=1\) is Manhattan, \(p=2\) is Euclidean, \(p \to \infty\) is Chebyshev. |
(C++ implemented; Python binding pending) |
One-Dimensional Distance |
Absolute difference along a single spatial or temporal dimension, used as the temporal component in spatiotemporal models. |
(C++ implemented; Python binding pending) |
Distance Matrix File |
Reads distances from a precomputed |
(C++ implemented; Python binding pending) |
Spatiotemporal Distance |
Weighted combination of spatial and temporal distances, supporting orthogonal and oblique modes. |
(C++ implemented; Python binding pending) |
CRS Distance¶
The coordinate-reference-system distance is the most commonly used metric, automatically selecting the calculation method based on the CRS.
Projected coordinates (
is_geographic=False) — Euclidean distance:\[d_{ij} = \sqrt{(u_i - u_j)^2 + (v_i - v_j)^2}\]Geographic coordinates (
is_geographic=True) — great-circle distance (geodesic distance).
Usage:
from pygwmodel import CRSDistance
# Projected coordinate system (default)
dist = CRSDistance(is_geographic=False)
# Geographic coordinate system
dist = CRSDistance(is_geographic=True)
Kernel Functions and Weights¶
Kernel functions convert distances \(d_{ij}\) into weights \(w_{ij}\).
pygwmodel supports five kernel functions, configured via
BandwidthWeight.
Kernel |
Formula |
Enum Value |
|---|---|---|
Gaussian |
\(w_{ij} = \exp\left(-\dfrac{d_{ij}^2}{2b^2}\right)\) |
|
Exponential |
\(w_{ij} = \exp\left(-\dfrac{|d_{ij}|}{b}\right)\) |
|
Bisquare |
\(w_{ij} = \begin{cases} \left(1 - \left(\frac{d_{ij}}{b}\right)^2\right)^2, & d_{ij} < b \\ 0, & \text{otherwise} \end{cases}\) |
|
Tricube |
\(w_{ij} = \begin{cases} \left(1 - \left(\frac{d_{ij}}{b}\right)^3\right)^3, & d_{ij} < b \\ 0, & \text{otherwise} \end{cases}\) |
|
Boxcar |
\(w_{ij} = \begin{cases} 1, & d_{ij} < b \\ 0, & \text{otherwise} \end{cases}\) |
|
Here \(b\) is the bandwidth and \(d_{ij}\) is the distance from sample \(i\) to sample \(j\).
Gaussian and Exponential are continuous kernels — all samples receive non-zero weights. Bisquare, Tricube, and Boxcar are truncated kernels — samples beyond the bandwidth receive zero weight, which is useful for emphasising local effects.
Usage:
from pygwmodel import BandwidthWeight
# Gaussian kernel (default)
bw = BandwidthWeight(bandwidth=36.0, adaptive=True,
kernel=BandwidthWeight.Kernel.Gaussian)
# Bisquare kernel
bw = BandwidthWeight(bandwidth=5000.0, adaptive=False,
kernel=BandwidthWeight.Kernel.Bisquare)
Bandwidth¶
The bandwidth \(b\) controls the rate at which spatial weights decay and is the most important parameter in GW models.
Bandwidth Types¶
Fixed bandwidth: The bandwidth value is a distance. Weights are computed directly as \(w = k(d; b)\).
Adaptive bandwidth: The bandwidth value is a neighbour count. For focus point \(i\), the effective distance bandwidth is the distance to the \(b\)-th nearest neighbour. Different locations can use different effective distance bandwidths, making this suitable for datasets with non-uniform sample density.
Usage:
# Adaptive bandwidth: b=36 means use distance to the 36th nearest neighbour
bw = BandwidthWeight(bandwidth=36.0, adaptive=True)
# Fixed bandwidth: b=5000.0 means distance threshold of 5000 coordinate units
bw = BandwidthWeight(bandwidth=5000.0, adaptive=False)
Bandwidth Selection¶
If you are unsure about the right bandwidth value, the algorithm can select it automatically.
GWRBasic:
from pygwmodel import GWRBasic
algorithm = GWRBasic(data, y, x, weight, distance).fit(
optimize_bw=GWRBasic.BandwidthSelectionCriterionType.CV
)
# The optimised bandwidth
print(algorithm.weight.bandwidth)
GWRMultiscale (each variable’s bandwidth is optimised independently during backfitting):
from pygwmodel import GWRMultiscale
# BandwidthInitilizeType.Null (default) lets the algorithm auto-select
algorithm = GWRMultiscale(
data, y, x, weights,
bandwidth_initilize=None, # all auto-select
bandwidth_selection_approach=None # all use CV
).fit()
# Check the optimised bandwidths
for w in algorithm.weights:
print(w.bandwidth)
Bandwidth selection criteria:
CV (Cross-Validation): Minimizes the cross-validation residual sum of squares.
AIC (Akaike Information Criterion): Minimizes the AIC value.
Spatial Weight Configuration¶
A SpatialWeight combines a distance metric
and a bandwidth weight, created via the factory method:
from pygwmodel import SpatialWeight, BandwidthWeight, CRSDistance
sw = SpatialWeight.create(
distance=CRSDistance(is_geographic=False),
weight=BandwidthWeight(bandwidth=36.0, adaptive=True)
)