analyze_mgwr
analyze_mgwr(
df,
outcome=None,
covariates=None,
*,
gdf,
period=None,
entity=None,
time=None,
kernel='bisquare',
criterion='AICc',
max_iter=200,
tiles=None,
title=None,
)Fit a multiscale GWR: every term gets its own spatial scale (bandwidth).
MGWR relaxes GWR’s single shared bandwidth: a backfitting algorithm (mgwr’s Sel_BW(multi=True) + MGWR) selects one adaptive bandwidth per term, so each covariate’s association can vary at its own spatial scale. Following the MGWR requirement, the outcome and covariates are always z-standardized, so local coefficients are on the standardized scale (a note records this). Local significance applies per-term da Silva & Fotheringham corrected alphas at the 5% nominal level.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| df | pd.DataFrame | Long panel (or cross section) holding the outcome and covariates per entity. | required |
| outcome | str | None | Numeric outcome column. Defaults to the outcome declared via :func:geometrics.set_roles. |
None |
| covariates | str | Sequence[str] | None | Numeric covariate column(s). Default to the covariates declared via :func:geometrics.set_roles. |
None |
| gdf | gpd.GeoDataFrame | Entity geometry; must carry the same entity-id column as df. Calibration coordinates are the polygon centroids in a metric CRS. |
required |
| period | Any | Period to analyze. Defaults to the latest period when df has a time dimension (a note records this). |
None |
| entity | str | None | Panel identifiers; default to the ids declared via :func:geometrics.set_panel. |
None |
| time | str | None | Panel identifiers; default to the ids declared via :func:geometrics.set_panel. |
None |
| kernel | str | Kernel weighting function: "bisquare" (default), "gaussian" or "exponential". |
'bisquare' |
| criterion | str | Bandwidth-selection criterion: "AICc" (default), "AIC", "BIC" or "CV". |
'AICc' |
| max_iter | int | Maximum number of multiscale backfitting iterations. | 200 |
| tiles | str | None | MapLibre base-map style for the coefficient maps, or None (default) for the vector backend (deterministic PNG export). |
None |
| title | str | None | Title for the residual map; per-term maps append the term label. | None |
Returns
| Name | Type | Description |
|---|---|---|
| MGWRResult | Frozen result with the per-entity local frame (df), one diverging coefficient map per term (figs), the residual map (fig — mgwr does not define a local R² under multiple bandwidths), the summary and bandwidth tables (gt / gt_bw), the per-term bw / adj_alpha / critical_t dicts and the fitted mgwr results (model_obj). |
Raises
| Name | Type | Description |
|---|---|---|
| KeyError | If the outcome or a covariate is not a column of df. |
|
| TypeError | If a focal variable is not numeric, or df/gdf have the wrong type. |
|
| ValueError | If roles cannot be resolved, arguments are invalid, or too few complete observations remain after alignment. |
Examples
A 3x3 lattice cross-section (bandwidths selected by backfitting):
import geopandas as gpd
import pandas as pd
from shapely.geometry import box
from geometrics.gwr import analyze_mgwr
gdf = gpd.GeoDataFrame(
{"cell": [f"c{i}" for i in range(9)]},
geometry=[box(78 + i % 3, 20 + i // 3, 79 + i % 3, 21 + i // 3) for i in range(9)],
crs="EPSG:4326",
)
df = pd.DataFrame(
{
"cell": [f"c{i}" for i in range(9)],
"x1": [0.1, 0.9, 0.4, 0.7, 0.2, 0.8, 0.5, 0.3, 0.6],
"y": [0.2, 1.4, 0.8, 1.5, 0.6, 2.0, 1.4, 1.0, 1.9],
}
)
res = analyze_mgwr(df, "y", ["x1"], gdf=gdf, entity="cell", tiles=None)
print(sorted(res.bw))