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))