Skip to content

Commit 07d0195

Browse files
committed
Minor adjustments to printouts and spatial impacts
1 parent 295430f commit 07d0195

File tree

7 files changed

+87
-36
lines changed

7 files changed

+87
-36
lines changed

spreg/dgp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ def make_wxg(wx,gamma):
291291

292292
def dgp_errproc(u,w,lam=0.5,model='sar',imethod='power_exp'):
293293
"""
294-
dgp_sar: generates pure spatial error process
294+
dgp_errproc: generates pure spatial error process
295295
296296
Arguments:
297297
----------
@@ -303,7 +303,7 @@ def dgp_errproc(u,w,lam=0.5,model='sar',imethod='power_exp'):
303303
304304
Returns:
305305
--------
306-
y : vector of observations following a pure SAR process
306+
y : vector of observations following a spatial AR or MA process
307307
308308
Examples
309309
--------

spreg/ml_lag.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,11 @@ class ML_Lag(BaseML_Lag):
340340
tolerance criterion in mimimize_scalar function and inverse_product
341341
spat_diag : boolean
342342
If True, then compute Common Factor Hypothesis test when applicable
343-
spat_impacts : boolean
344-
If True, include average direct impact (ADI), average indirect impact (AII),
345-
and average total impact (ATI) in summary results
343+
spat_impacts : string
344+
Include average direct impact (ADI), average indirect impact (AII),
345+
and average total impact (ATI) in summary results.
346+
Options are 'simple', 'full', 'power', or None.
347+
See sputils.spmultiplier for more information.
346348
vm : boolean
347349
if True, include variance-covariance matrix in summary
348350
results
@@ -594,7 +596,7 @@ def __init__(
594596
slx_lags=0,
595597
method="full",
596598
epsilon=0.0000001,
597-
spat_impacts=True,
599+
spat_impacts="simple",
598600
vm=False,
599601
spat_diag=True,
600602
name_y=None,
@@ -642,7 +644,7 @@ def __init__(
642644
if spat_diag and slx_lags==1:
643645
diag_out = _spat_diag_out(self, w, 'yend', ml=True)
644646
if spat_impacts and slx_lags == 0:
645-
impacts = _summary_impacts(self, _spmultiplier(w, self.rho))
647+
impacts = _summary_impacts(self, _spmultiplier(w, self.rho, method=spat_impacts), spat_impacts)
646648
try:
647649
diag_out += impacts
648650
except TypeError:

spreg/ml_lag_regimes.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ class ML_Lag_Regimes(BaseML_Lag, REGI.Regimes_Frame):
6666
the spatial parameter is fixed accross regimes.
6767
spat_diag : boolean
6868
If True, then compute Common Factor Hypothesis test when applicable
69-
spat_impacts : boolean
70-
If True, include average direct impact (ADI), average indirect impact (AII),
71-
and average total impact (ATI) in summary results
69+
spat_impacts : string
70+
Include average direct impact (ADI), average indirect impact (AII),
71+
and average total impact (ATI) in summary results.
72+
Options are 'simple', 'full', 'power', or None.
73+
See sputils.spmultiplier for more information.
7274
cores : boolean
7375
Specifies if multiprocessing is to be used
7476
Default: no multiprocessing, cores = False
@@ -318,7 +320,7 @@ def __init__(
318320
regime_lag_sep=False,
319321
cores=False,
320322
spat_diag=True,
321-
spat_impacts=True,
323+
spat_impacts="simple",
322324
vm=False,
323325
name_y=None,
324326
name_x=None,
@@ -448,8 +450,9 @@ def __init__(
448450
diag_out = _spat_diag_out(self, w, 'yend', ml=True)
449451
else:
450452
self.title = ("MAXIMUM LIKELIHOOD SPATIAL LAG - REGIMES"+ " (METHOD = "+ method+ ")")
453+
451454
if spat_impacts and slx_lags == 0:
452-
impacts = _summary_impacts(self, _spmultiplier(w, self.rho))
455+
impacts = _summary_impacts(self, _spmultiplier(w, self.rho, method=spat_impacts), spat_impacts, regimes=True)
453456
try:
454457
diag_out += impacts
455458
except TypeError:
@@ -605,7 +608,7 @@ def ML_Lag_Regimes_Multi(
605608
if spat_diag and slx_lags == 1:
606609
results[r].other_mid += _spat_diag_out(results[r], None, 'yend', ml=True)
607610
if spat_impacts and slx_lags == 0:
608-
results[r].other_mid += _summary_impacts(results[r], _spmultiplier(results[r].w, results[r].rho))
611+
results[r].other_mid += _summary_impacts(results[r], _spmultiplier(results[r].w, results[r].rho, method=spat_impacts), spat_impacts)
609612
counter += 1
610613
self.multi = results
611614
self.chow = REGI.Chow(self)
@@ -644,7 +647,7 @@ def _work(
644647
model.schwarz = DIAG.schwarz(reg=model)
645648
model.slx_lags = slx_lags
646649
model.w = w_r
647-
model.rho = model.betas[-1]
650+
model.rho = model.betas[-1]
648651
return model
649652

650653

spreg/output.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import textwrap as TW
66
import numpy as np
77
import pandas as pd
8-
import math
98
from . import diagnostics as diagnostics
109
from . import diagnostics_tsls as diagnostics_tsls
1110
from . import diagnostics_sp as diagnostics_sp
11+
from .sputils import _sp_effects
1212

1313
__all__ = []
1414

@@ -568,7 +568,7 @@ def _summary_iteration(reg):
568568

569569
return txt
570570

571-
def _summary_impacts(reg, spmult):
571+
def _summary_impacts(reg, spmult, spat_impacts, slx_lags=0, regimes=False):
572572
"""
573573
Spatial direct, indirect and total effects in spatial lag model.
574574
Uses multipliers computed by sputils._spmultipliers.
@@ -577,21 +577,24 @@ def _summary_impacts(reg, spmult):
577577
----------
578578
reg: spreg regression object
579579
spmult: spatial multipliers as a dictionary
580+
spat_impacts: spatial impacts method as string
581+
slx_lags: int, number of spatial lags of X in the model
582+
regimes: boolean, True if regimes model
580583
581584
Returns
582585
-------
583586
strings with direct, indirect and total effects
584587
585588
"""
586-
variables = reg.output[reg.output['var_type'].isin(['x', 'wx', 'yend']) & (reg.output.index != 0)]
589+
variables = reg.output.query("var_type in ['x', 'yend'] and index != 0")
590+
if regimes:
591+
variables = variables[~variables['var_names'].str.endswith('_CONSTANT')]
587592
variables_index = variables.index
588-
m1 = spmult['ati']
589-
btot = m1 * reg.betas[variables_index]
590-
m2 = spmult['adi']
591-
bdir = m2 * reg.betas[variables_index]
592-
m3 = spmult['aii']
593-
bind = m3 * reg.betas[variables_index]
593+
594+
btot, bdir, bind = _sp_effects(reg, variables, spmult, slx_lags)
595+
594596
strSummary = "\nSPATIAL LAG MODEL IMPACTS\n"
597+
strSummary += "Impacts computed using the '" + spat_impacts + "' method.\n"
595598
strSummary += " Variable Direct Indirect Total\n"
596599
for i in range(len(variables)):
597600
strSummary += "%20s %12.4f %12.4f %12.4f\n" % (

spreg/sputils.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ def _spmultiplier(w, rho, method="simple", mtol=0.00000001):
307307
adii0 = np.sum(np.diag(invirw0))
308308
multipliers["adi"] = adii0 / n
309309
elif method == "power":
310-
wf = w.full()[0]
311-
ws3 = SP.csr_array(wf)
310+
ws3 = w.to_sparse(fmt='csr')
312311
rhop = rho
313312
ww = ws3
314313
pow = 1
@@ -329,6 +328,45 @@ def _spmultiplier(w, rho, method="simple", mtol=0.00000001):
329328
multipliers["aii"] = multipliers["ati"] - multipliers["adi"]
330329
return (multipliers)
331330

331+
def _sp_effects(reg, variables, spmult, slx_lags=0):
332+
"""
333+
Calculate spatial lag, direct and indirect effects
334+
335+
Attributes
336+
----------
337+
reg : regression object
338+
variables : chunk of self.output with variables to calculate effects
339+
spmult : dictionary with spatial multipliers
340+
slx_lags : number of SLX lags
341+
342+
Returns
343+
-------
344+
btot : total effects
345+
bdir : direct effects
346+
bind : indirect effects
347+
"""
348+
variables_index = variables.index
349+
m1 = spmult['ati']
350+
btot = m1 * reg.betas[variables_index]
351+
m2 = spmult['adi']
352+
bdir = m2 * reg.betas[variables_index]
353+
354+
# Assumes all SLX effects are indirect effects. Needs revision by LA.
355+
if slx_lags > 0:
356+
variables_wx = reg.output.query("var_type == 'wx'")
357+
variables_wx_index = variables_wx.index
358+
359+
chunk_size = len(variables)
360+
for i in range(slx_lags):
361+
start_idx = i * chunk_size
362+
end_idx = start_idx + chunk_size
363+
chunk_indices = variables_wx_index[start_idx:end_idx]
364+
btot += m1 * reg.betas[chunk_indices]
365+
bind = btot - bdir
366+
else:
367+
m3 = spmult['aii']
368+
bind = m3 * reg.betas[variables_index]
369+
return btot, bdir, bind
332370

333371
def _test():
334372
import doctest

spreg/twosls_sp.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,11 @@ class GM_Lag(BaseGM_Lag):
238238
If True, then use n-k to estimate sigma^2. If False, use n.
239239
spat_diag : boolean
240240
If True, then compute Anselin-Kelejian test and Common Factor Hypothesis test (if applicable)
241-
spat_impacts : boolean
242-
If True, include average direct impact (ADI), average indirect impact (AII),
243-
and average total impact (ATI) in summary results
241+
spat_impacts : string
242+
Include average direct impact (ADI), average indirect impact (AII),
243+
and average total impact (ATI) in summary results.
244+
Options are 'simple', 'full', 'power', or None.
245+
See sputils.spmultiplier for more information.
244246
vm : boolean
245247
If True, include variance-covariance matrix in summary
246248
results
@@ -505,7 +507,7 @@ def __init__(
505507
gwk=None,
506508
sig2n_k=False,
507509
spat_diag=True,
508-
spat_impacts=True,
510+
spat_impacts="simple",
509511
vm=False,
510512
name_y=None,
511513
name_x=None,
@@ -585,10 +587,11 @@ def __init__(
585587
self.output['regime'], self.output['equation'] = (0, 0)
586588
self.other_top = _spat_pseudo_r2(self)
587589
diag_out = None
590+
588591
if spat_diag:
589592
diag_out = _spat_diag_out(self, w, 'yend')
590593
if spat_impacts and slx_lags == 0:
591-
impacts = _summary_impacts(self, _spmultiplier(w, self.rho))
594+
impacts = _summary_impacts(self, _spmultiplier(w, self.rho, method=spat_impacts), spat_impacts, slx_lags)
592595
try:
593596
diag_out += impacts
594597
except TypeError:

spreg/twosls_sp_regimes.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ class GM_Lag_Regimes(TSLS_Regimes, REGI.Regimes_Frame):
8888
matrix must have ones along the main diagonal.
8989
sig2n_k : boolean
9090
If True, then use n-k to estimate sigma^2. If False, use n.
91-
spat_impacts : boolean
92-
If True, include average direct impact (ADI), average indirect impact (AII),
93-
and average total impact (ATI) in summary results
91+
spat_impacts : string
92+
Include average direct impact (ADI), average indirect impact (AII),
93+
and average total impact (ATI) in summary results.
94+
Options are 'simple', 'full', 'power', or None.
95+
See sputils.spmultiplier for more information.
9496
spat_diag : boolean
9597
If True, then compute Anselin-Kelejian test and Common Factor Hypothesis test (if applicable)
9698
vm : boolean
@@ -455,7 +457,7 @@ def __init__(
455457
gwk=None,
456458
sig2n_k=False,
457459
spat_diag=True,
458-
spat_impacts=True,
460+
spat_impacts="simple",
459461
constant_regi="many",
460462
cols2regi="all",
461463
regime_lag_sep=False,
@@ -643,7 +645,7 @@ def __init__(
643645
if spat_diag:
644646
diag_out = _spat_diag_out(self, w, 'yend')
645647
if spat_impacts and slx_lags == 0:
646-
impacts = _summary_impacts(self, _spmultiplier(w, self.rho))
648+
impacts = _summary_impacts(self, _spmultiplier(w, self.rho, method=spat_impacts), spat_impacts, regimes=True)
647649
try:
648650
diag_out += impacts
649651
except TypeError:
@@ -847,7 +849,7 @@ def GM_Lag_Regimes_Multi(
847849
if spat_diag:
848850
results[r].other_mid += _spat_diag_out(results[r], results[r].w, 'yend')
849851
if spat_impacts and slx_lags == 0:
850-
results[r].other_mid += _summary_impacts(results[r], _spmultiplier(results[r].w, results[r].rho))
852+
results[r].other_mid += _summary_impacts(results[r], _spmultiplier(results[r].w, results[r].rho, method=spat_impacts), spat_impacts)
851853
counter += 1
852854
self.multi = results
853855
if robust == "hac":

0 commit comments

Comments
 (0)