neighbayes.models.SLX¶
-
class neighbayes.models.SLX(formula=
None, data=None, y=None, X=None, W=None, priors=None, logdet_method=None, robust=False, w_vars=None, logdet_refit=True, logdet_refit_pad_sd=10.0, logdet_aaa_check=True, logdet_probe_check=True)[source]¶ Bayesian SLX (Spatial Lag X) model.
Adds spatial lags of the regressors \(X\) to a standard linear model, without any spatial dependence in \(y\):
\[y = X\beta + WX\theta + \varepsilon, \quad \varepsilon \sim N(0, \sigma^2 I).\]The sampled coefficient vector stacks the local and lagged-regressor blocks as \([\beta, \theta]\). There is no Jacobian term because there is no spatial lag of \(y\).
- Parameters:¶
- formula : str, optional¶
Wilkinson-style formula, e.g.
"y ~ x1 + x2". Requiresdata. Intercept is included by default; suppress with"y ~ x - 1".- data : pandas.DataFrame or geopandas.GeoDataFrame, optional¶
Data source for formula mode.
- y : array-like, optional¶
Dependent variable of shape
(n,). Required in matrix mode.- X : array-like or pandas.DataFrame, optional¶
Design matrix. Required in matrix mode. DataFrame columns are preserved as feature names.
- W : libpysal.graph.Graph or scipy.sparse matrix¶
Spatial weights of shape
(n, n). Used to construct theWXblock. Accepts alibpysal.graph.Graphor anyscipy.sparsematrix; legacylibpysal.weights.Wis not accepted (usew.sparseorlibpysal.graph.Graph.from_W(w)). Should be row-standardized.- priors : dict, optional¶
Override default priors. Supported keys:
beta_mu(array or float, optional): Normal prior mean for coefficients \([eta, heta]\). Default is Gelman et al. (2008) weakly-informative mean (mean(y)for intercept/constant columns, 0 for slopes).beta_sigma(array or float, optional): Normal prior std for coefficients. Default is Gelman et al. (2008) weakly-informative scale:2.5 * sd(y)for intercept/constant columns and2.5 * sd(y) / sd(x_j)for each slope.sigma2_alpha(float, default 2.0): Shape of the InverseGamma prior on \(\sigma^2\).sigma2_beta(float, defaultVar(y)): Scale of the InverseGamma prior on \(\sigma^2\).nu(float, default 4.0): Fixed Student-t degrees of freedom (only used whenrobust=True).
- logdet_method : str, optional¶
Accepted for API consistency with the spatial-lag/error models but unused (SLX has no spatial Jacobian).
- robust : bool, default False¶
If True, replace the Normal error with Student-t. See Robust regression below.
- w_vars : list of str, optional¶
Names of X columns to spatially lag. By default all non-constant columns are lagged. Pass a subset to restrict which variables receive a spatial lag, e.g.
w_vars=["income", "density"]. SLX requires at least one WX column; if filtering eliminates all of them a ValueError is raised.
Notes
Direct effects equal \(\beta\) and indirect effects equal \(\theta\). There is no global spillover multiplier because \(y\) has no spatial autoregression.
Robust regression
When
robust=True, the error distribution is changed from Normal to Student-t:\[\varepsilon \sim t_\nu(0, \sigma^2 I)\]where \(\nu\) is a fixed hyperparameter set by
priors={"nu": value}(default 4, LeSage’srval); larger values approach the Normal. Values must exceed 2 so the variance exists.-
__init__(formula=
None, data=None, y=None, X=None, W=None, priors=None, logdet_method=None, robust=False, w_vars=None, logdet_refit=True, logdet_refit_pad_sd=10.0, logdet_aaa_check=True, logdet_probe_check=True)[source]¶
Methods
__init__([formula, data, y, X, W, priors, ...])fit([draws, tune, chains, target_accept, ...])Draw samples from the posterior.
Return fitted values at posterior mean parameters.
Return residuals
y - fitted_values.Run Bayesian LM specification tests and return a summary table.
spatial_diagnostics_decision([alpha, format])Return a model-selection decision from Bayesian LM test results.
spatial_effects([return_posterior_samples])Compute Bayesian inference for direct, indirect, and total impacts.
summary([var_names])Return posterior summary table.
Attributes
Return the ArviZ InferenceData from the most recent fit.
Return the PyMC model object built for the most recent fit.
-
fit(draws=
2000, tune=1000, chains=4, target_accept=None, random_seed=None, progressbar=True, sampler=None, gibbs_backend='auto', thin=1, n_jobs=-1, idata_kwargs=None, **sample_kwargs)[source]¶ Draw samples from the posterior.
Dispatches to this model’s Gibbs sampler (
sampler="gibbs") or NUTS (sampler="nuts"). WhensamplerisNone(default), Gibbs is used if the model has a registered Gibbs sampler, otherwise NUTS.- Parameters:¶
- draws : int¶
Post-warmup draws, warmup steps, and number of chains.
- tune : int¶
Post-warmup draws, warmup steps, and number of chains.
- chains : int¶
Post-warmup draws, warmup steps, and number of chains.
- target_accept : float, optional¶
Target acceptance rate for NUTS. NUTS-only: passing it with the Gibbs sampler raises
TypeError. Defaults to0.9for NUTS.- random_seed : int, optional¶
Seed for reproducibility.
- progressbar : bool, default True¶
Show progress bar(s) during sampling.
- sampler : {"gibbs", "nuts", None}, default None¶
Sampling method.
Noneauto-selects Gibbs when this model has one, else NUTS.- gibbs_backend : {"auto", "jax", "numpy"}, default "auto"¶
Execution backend for the Gibbs sampler.
"auto"uses JAX when installed and supported by the family, else NumPy. Ignored for NUTS.- thin : int, default 1¶
Keep every
thin-th post-warmup Gibbs draw (Gibbs only).- n_jobs : int, default -1¶
Parallel workers for the NumPy Gibbs path (Gibbs only).
- idata_kwargs : dict, optional¶
{"log_likelihood": True}stores the complete Jacobian-corrected pointwise log-likelihood thataz.loo/az.waic/az.compareneed, for Gibbs and NUTS alike. Off by default, as in PyMC: it holds one value per draw, chain, and observation (16 GB at n = 250,000 with 4 × 2,000 draws). For NUTS the dict is also passed topm.sample.- **sample_kwargs¶
For NUTS, forwarded to
pm.sample(nuts_sampler=...); for Gibbs, the family’s declared options (an unsupported key raises).
- Return type:¶
arviz.InferenceData
- property inference_data : arviz.data.inference_data.InferenceData | None[source]¶
Return the ArviZ InferenceData from the most recent fit.
- property pymc_model : pymc.model.core.Model | None[source]¶
Return the PyMC model object built for the most recent fit.
For Gibbs-fitted models the PyMC model is not constructed during sampling; it is built lazily on first access so that downstream consumers (e.g. bridge sampling for marginal likelihoods) can evaluate
logpand the prior under the same model definition used by the NUTS path.
- residuals()[source]¶
Return residuals
y - fitted_values.- Returns:¶
Residual vector
y - fitted_valueson the same scale asfitted_values().- Return type:¶
np.ndarray
- spatial_diagnostics()[source]¶
Run Bayesian LM specification tests and return a summary table.
Looks up the diagnostic suite registered for this model class and calls each test function on this fitted model, collecting the results into a tidy DataFrame. The set of tests depends on the model type — for example, an OLS model runs LM-Lag, LM-Error, LM-SDM-Joint, and LM-SLX-Error-Joint, while an SAR model runs LM-Error, LM-WX, and Robust-LM-WX. Panel models run the
Panel--prefixed analogues (e.g. Panel-LM-Lag).Requires the model to have been fit (
.fit()called) and a spatial weights matrixWto have been supplied at construction time.- Returns:¶
DataFrame indexed by test name with columns:
Column
Description
statistic
Posterior mean of the LM statistic
median
Posterior median of the LM statistic
df
Degrees of freedom for the \(\chi^2\) reference
p_value
Bayesian p-value:
1 - chi2.cdf(mean, df)ci_lower
Lower bound of 95% credible interval (2.5%)
ci_upper
Upper bound of 95% credible interval (97.5%)
The DataFrame has
attrs["model_type"](class name) andattrs["n_draws"](total posterior draws) metadata.- Return type:¶
pandas.DataFrame
- Raises:¶
RuntimeError – If the model has not been fit yet.
ValueError – If no spatial weights matrix
Wwas supplied.
See also
spatial_diagnostics_decisionModel-selection decision based on the test results.
spatial_effectsPosterior inference for direct/indirect/total impacts.
Examples
>>> ols = OLS(formula="price ~ income + crime", data=df, W=w) >>> ols.fit() >>> ols.spatial_diagnostics() statistic median df p_value ci_lower ci_upper LM-Lag 3.21 2.98 1 0.073 0.12 8.54 LM-Error 5.67 5.34 1 0.017 0.34 12.10 LM-SDM-Joint 7.89 7.12 4 0.096 1.23 18.32 LM-SLX-Error-Joint 6.45 5.98 4 0.168 0.89 15.67
-
spatial_diagnostics_decision(alpha=
0.05, format='graphviz')[source]¶ Return a model-selection decision from Bayesian LM test results.
Implements the decision tree from Koley and Bera [2024] (the Bayesian analogue of the classical
stge_kbprocedure in Anselin et al. [1996]). Panel models use thePanel--prefixed test analogues and the panel decision specs, following Elhorst [2014]. The decision logic depends on the current model type and the pattern of significant tests:From OLS (6-test decision tree):
If only LM-Lag is significant → SAR.
If only LM-Error is significant → SEM.
If both are significant → use the Anselin–Florax / Koley–Bera robust pair: Robust-LM-Lag → SAR, Robust-LM-Error → SEM, both → SARAR. If neither robust test is significant, fall back to the lower raw p-value.
If neither naive test is significant → OLS.
From SAR (3-test decision tree):
LM-Error significant → SARAR; LM-WX significant → SDM; Robust-LM-WX significant → SDM.
From SEM (2-test decision tree):
LM-Lag significant → SARAR; LM-WX significant → SDEM.
From SLX (4-test decision tree):
Robust-LM-Lag-SDM significant → SDM; Robust-LM-Error-SDEM significant → SDEM; both → MANSAR; neither → SLX.
From SDM: LM-Error-SDM significant → MANSAR; else SDM.
From SDEM: LM-Lag-SDEM significant → MANSAR; else SDEM.
- Parameters:¶
- alpha : float, default 0.05¶
Significance level for the Bayesian p-values.
- format : {"graphviz", "ascii", "model"}, default "graphviz"¶
Output format.
"model"returns the recommended-model name string."ascii"returns an indented box-drawing rendering of the full decision tree with the chosen path highlighted."graphviz"returns agraphviz.Digraphobject that renders inline in Jupyter; if the optionalgraphvizpackage is not installed aUserWarningis issued and the ASCII rendering is returned instead.
- Returns:¶
Recommended model name when
format="model", an ASCII tree string whenformat="ascii", or agraphviz.Digraphwhenformat="graphviz"(with ASCII fallback on missing dep).- Return type:¶
str or graphviz.Digraph
See also
spatial_diagnosticsCompute the Bayesian LM test statistics.
References
Koley and Bera [2024], Anselin et al. [1996], Elhorst [2014]
-
spatial_effects(return_posterior_samples=
False)[source]¶ Compute Bayesian inference for direct, indirect, and total impacts.
Computes impact measures for each posterior draw, then summarizes the posterior distribution with means, 95% credible intervals, and Bayesian p-values. This is the fully Bayesian analog of the simulation-based approach in LeSage and Pace [2009] and the asymptotic variance formulas in Arbia et al. [2020].
Models without a spatial lag on y do not exhibit global feedback propagation through \((I-\\rho W)^{-1}\). However, models with spatially lagged covariates (SLX, SDEM) can still have non-zero neighbor spillovers captured in the indirect term.
- Parameters:¶
- Returns:¶
If return_posterior_samples is
False(default), returns a DataFrame indexed by feature names with columns for posterior means, credible-interval bounds, and Bayesian p-values.If return_posterior_samples is
True, returns(DataFrame, dict)where the dict has keys"direct","indirect","total", each mapping to a(G, k)array of posterior draws.- Return type:¶