explore_moran_over_time
explore_moran_over_time(
df,
var,
*,
gdf,
w=None,
entity=None,
time=None,
permutations=999,
seed=12345,
title=None,
)Track global Moran’s I in var period by period on a fixed entity set.
The long panel is pivoted to one row per entity and one column per period, and a single entity set — the entities with complete data across every kept period — is used throughout, so the same (possibly restricted) weights apply to every period and the Moran’s I values are comparable over time. Periods with no data at all and entities with incomplete series are dropped with a note. Each period’s test uses permutations conditional permutations (:class:esda.moran.Moran).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| df | pd.DataFrame | Long panel holding var per (entity, period). |
required |
| var | str | Numeric column of df to track. |
required |
| gdf | gpd.GeoDataFrame | Entity geometry; must carry the same entity-id column as df. |
required |
| w | W | None | libpysal weights aligned to the gdf entity ids. None builds the default weights (queen contiguity for polygons, 6-nearest-neighbor otherwise) with a :class:~geometrics.GeometricsWarning. When entities drop, the weights are restricted (w_subset) and their transform re-applied. |
None |
| entity | str | None | Panel identifiers; default to the ids declared via :func:geometrics.set_panel. Both are required here. |
None |
| time | str | None | Panel identifiers; default to the ids declared via :func:geometrics.set_panel. Both are required here. |
None |
| permutations | int | Number of conditional permutations behind each period’s p_sim / z_sim. |
999 |
| seed | int | None | esda’s :class:~esda.moran.Moran draws its permutations from NumPy’s global random state and exposes no seed argument, so when seed is not None geometrics calls numpy.random.seed(seed) immediately before each period’s test — every period’s p-value is then reproducible on its own, independent of which other periods are present. None leaves the random state untouched. |
12345 |
| title | str | None | Figure title. Defaults to "Global Moran's I over time: <label>". |
None |
Returns
| Name | Type | Description |
|---|---|---|
| MoranOverTimeResult | Frozen result with one row per period (period, moran_i, z_sim, p_sim, n_obs), the line-and-marker fig (filled markers flag p_sim < 0.05; the dashed line marks E[I] under spatial randomness) and w_spec. |
Examples
Two periods on a four-cell strip with a smooth west-east gradient:
import geopandas as gpd
import pandas as pd
from shapely.geometry import box
from geometrics.dependence import explore_moran_over_time
from geometrics.weights import make_weights
gdf = gpd.GeoDataFrame(
{"region": ["a", "b", "c", "d"]},
geometry=[box(i, 0, i + 1, 1) for i in range(4)],
crs="EPSG:4326",
)
df = pd.DataFrame(
{
"region": ["a", "b", "c", "d"] * 2,
"year": [2000] * 4 + [2010] * 4,
"gdppc": [1.0, 2.0, 3.0, 4.0, 1.5, 2.5, 3.5, 4.5],
}
)
res = explore_moran_over_time(
df, "gdppc", gdf=gdf, w=make_weights(gdf), entity="region", time="year",
permutations=99,
)
print(res.df[["period", "n_obs"]].to_dict("list"))