ivspatial — nonparametric tests of spatial independence
ivspatial tests whether values observed at spatial units — cells of a grid, polygons such as
counties, irregularly located points, or the nodes of a network — are independent and
identically distributed (i.i.d.) across the units. It implements the procedure of
Ashtari Nezhad, E. (2026). A nonparametric test of spatial independence on neighbourhood graphs.
The tests are rank based and exact: under independence their P-values are valid for every sample size, every graph and every continuous distribution, with no weight matrix, bandwidth or tuning to choose. Besides the P-value the package reports what kind of dependence is present (in the level, in the scale, or only among several neighbours), maps where it occurs, and can let the data choose the resolution with exact post-selection calibration.
The package can be used through a window (GUI, no programming) or through code (a Python function or a terminal command); both give identical results.
Full user guide: GUIDE.html — open it in any web browser, or run
ivspatial guide after installation (also the User guide button in the window).
1. Installation
You need Python 3.8 or later (https://www.python.org/downloads/; on Windows tick "Add python.exe to PATH"). Then
pip install ivspatial # from PyPI
pip install "ivspatial[all]" # with Excel, shapefile and map support
pip install git+https://github.com/emaad7/ivspatial # latest version from GitHub
numpy and scipy are installed automatically. Optional: pandas and openpyxl (Excel files),
pyshp (shapefiles; GeoJSON needs nothing), matplotlib (maps). An R version with the same
functions and a graphical interface: https://github.com/emaad7/ivspatial-r.
The graphical interface is included: type ivspatial-gui (or python -m ivspatial).
Without installing: download the ZIP from GitHub, unzip, run pip install numpy scipy, and
double-click run_gui_windows.bat (Windows), run_gui_mac_linux.command (macOS/Linux) or
ivspatial_gui.pyw.
2. Your data
- Points or grid cells: a CSV, TXT or Excel file with one row per site and columns for the coordinates (or the row and column indices of a grid) and for the variables.
- Polygons: a shapefile (
.shp, with its.dbfand.shx) or a GeoJSON file; the numeric attributes are the variables. - Networks or your own graph: the table of variables plus an edge list (a CSV file with two columns of site numbers, starting at 1).
- No missing values at the sites used (remove incomplete sites first). At least 20 sites; a few hundred are recommended.
Examples: examples/mercer_hall_wheat.csv (grain and straw yields of 500 plots on a 20 x 25
grid; columns row, col) and examples/baltimore_houses.csv (211 house sales with
coordinates X, Y, price and characteristics).
3. The neighbourhood graph
| Data | Graph | Command-line option |
|---|---|---|
| points | each site and its k nearest neighbours | --graph knn --x X --y Y --k 4 |
| points | Delaunay triangulation (contiguity of Voronoi cells) | --graph delaunay --x X --y Y |
| points | all sites within a distance | --graph band --x X --y Y --radius 1500 |
| grid | rook or queen contiguity from row/column indices | --graph lattice --row row --col col |
| grid | nrow x ncol, rows stored row by row | --graph grid --nrow 20 --ncol 25 |
| polygons | queen or rook contiguity | --graph polygons --contiguity queen |
| any | your own edge list | --graph edges --edges edges.csv |
4. Python
import numpy as np
import ivspatial as iv
tab = iv.read_table("examples/baltimore_houses.csv")
g = iv.knn_graph(np.c_[tab["X"], tab["Y"]], k=4)
res = iv.spatial_test(np.log(tab["PRICE"]), g, seed=1)
print(res) # report
res.p_value, res.reject # P-value of the combined test C4 and the decision
res.components # T_V(4,3), T_V(4,2), RM, RS with P-values
res.features # standardized features of T_V(3,2)
# residuals of a regression with exogenous regressors (no correction needed)
X = np.column_stack([tab[c] for c in ("NROOM", "NBATH", "SQFT", "AGE")])
print(iv.residual_test(np.log(tab["PRICE"]), X, g, seed=1))
# polygons
polys, att = iv.read_polygons("counties.shp")
gq = iv.polygon_contiguity_graph(polys, "queen")
print(iv.spatial_test(att["HR90"], gq, seed=1))
# many variables on one graph (one reference table, Benjamini-Hochberg adjustment)
w = iv.read_table("examples/mercer_hall_wheat.csv")
results, adj = iv.screen({"grain": w["grain"], "straw": w["straw"]}, iv.lattice_graph(20, 25), seed=1)
# data-driven resolution, several spatial lags, maps, null limits
x = np.log(tab["PRICE"])
iv.spatial_test(x, g, resolution="auto", lags=2, seed=1)
lf = iv.local_features(x, g) # local contributions for maps
iv.null_limit(g, d=4, s=2, value=35.2)
5. Command line
ivspatial examples/baltimore_houses.csv --x X --y Y --graph knn --k 4 --column PRICE --transform log --seed 1
ivspatial examples/mercer_hall_wheat.csv --graph lattice --row row --col col --all --seed 1
ivspatial counties.shp --column HR90 --residuals-on RD90,PS90,UE90,DV90,MA90,SOUTH --seed 1
ivspatial data.csv --x x --y y --column y --resolution auto --lags 2 --local local.csv
ivspatial null data.csv --x x --y y --graph delaunay --d 4 --s 2 --value 35
ivspatial gui
ivspatial guide
6. Reading the output
- C4 is the proposed test: the minimum P-value of four components, calibrated exactly from the same random rank arrangements. A P-value below the level means that the values are not i.i.d. across the sites.
- T_V(4,3) sees dependence in the joint distribution of a site and two neighbours, including dependence that is invisible in pairs; T_V(4,2) pairs with resolved tails; RM linear association of ranks (level); RS association of squared ranks (scale).
- Standardized features (about N(0,1) under independence):
c.lin|n.linsimilarity in level between a site and its neighbours;c.quad|n.quadextreme values next to extreme values;n.lin^2,n.quad^2the same between neighbours. |value| > 3 is notable. - Local features (
local_features, or Map in the window) show where a feature receives its contribution, like local indicators of spatial association; they are descriptive, not tests. - resolution="auto" chooses among T_V(d, s), d = 2..6, s = 2, 3, by the minimum-P rule and reports the choice; the P-value accounts for the choice exactly.
7. Notes
- The null hypothesis is that the values are i.i.d. A smooth trend or heteroskedasticity is detected as dependence; model the trend and test the residuals if needed.
- Residual tests are valid without correction when the regressors are exogenous. They are not valid for spatial-lag models (y regressed on W y); use a model-based bootstrap there.
- Ties (discrete data) are broken at random, which keeps the tests exact.
8. Citation
Ashtari Nezhad, E. (2026). A nonparametric test of spatial independence on neighbourhood graphs. Manuscript.
Ashtari Nezhad, E. (2026). ivspatial: nonparametric tests of spatial independence. Python package version 1.0.0. https://github.com/emaad7/ivspatial
License: MIT.
Metadata
Release files for ivspatial 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ivspatial-1.0.0.tar.gz | 205.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ivspatial-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 411.0 kB
Release files / ivspatial-1.0.0.tar.gz
| Download URL | ivspatial-1.0.0.tar.gz |
|---|---|
| Size | 205.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2b1ff90a7cbcf424f1b8c992ed33c33db1a1c613c5a1f43ce2709f7057895de5
|
|
BLAKE2b-256 checksum How to use checksums |
4b2e00e220811c724eef8ba58b6de6ba9573592f2f32955e7df75bc138469cda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.7
|
Release files / ivspatial-1.0.0-py3-none-any.whl
| Download URL | ivspatial-1.0.0-py3-none-any.whl |
|---|---|
| Size | 205.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d66f86c6cc1d8aeb632f2a1fab7d70d8a8aaa67d01c5bbcc26b4d479d9947725
|
|
BLAKE2b-256 checksum How to use checksums |
e858d34769351756addd0f28139fb7448c09044eb2e532a5b86948718f682944
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.7
|
Security for ivspatial 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.