Skip to main content

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 .dbf and .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.lin similarity in level between a site and its neighbours; c.quad|n.quad extreme values next to extreme values; n.lin^2, n.quad^2 the 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)

Source distribution for ivspatial 1.0.0
File Size Uploaded Provenance
ivspatial-1.0.0.tar.gz 205.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ivspatial 1.0.0
File Interpreter ABI Platform
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.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page