Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow custom variable names in summary #130

Merged
merged 1 commit into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions mgwr/gwr.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class GWR(GLM):
True to store full n by n hat matrix,
False to not store full hat matrix to minimize memory footprint (defalut).

name_x : list of strings
Names of independent variables for use in output

Attributes
----------
coords : array-like
Expand Down Expand Up @@ -207,7 +210,7 @@ class GWR(GLM):

def __init__(self, coords, y, X, bw, family=Gaussian(), offset=None,
sigma2_v1=True, kernel='bisquare', fixed=False, constant=True,
spherical=False, hat_matrix=False):
spherical=False, hat_matrix=False, name_x=None):
"""
Initialize class
"""
Expand All @@ -230,9 +233,10 @@ def __init__(self, coords, y, X, bw, family=Gaussian(), offset=None,
self.P = None
self.spherical = spherical
self.hat_matrix = hat_matrix
self.name_x = name_x

def _build_wi(self, i, bw):

if bw == np.inf:
wi = np.ones((self.n))
return wi
Expand Down Expand Up @@ -354,7 +358,7 @@ def fit(self, ini_params=None, tol=1.0e-5, max_iter=20, solve='iwls',
tr_STS = np.sum(np.array(rslt_list[-2]))
CCT = np.array(rslt_list[-1])
return GWRResults(self, params, predy, S, CCT, influ, tr_STS,
w)
w, self.name_x)


def predict(self, points, P, exog_scale=None, exog_resid=None,
Expand Down Expand Up @@ -437,6 +441,9 @@ class GWRResults(GLMResults):
n*1, final weight used for iteratively re-weighted least
sqaures; default is None

name_x : list of strings
Names of independent variables for use in output

Attributes
----------
model : GWR Object
Expand Down Expand Up @@ -602,10 +609,13 @@ class GWRResults(GLMResults):
p*1, predicted values generated by calling the GWR
predict method to predict dependent variable at
unsampled points ()

name_x : list of strings
Names of independent variables for use in output
"""

def __init__(self, model, params, predy, S, CCT, influ, tr_STS=None,
w=None):
w=None, name_x=None):
GLMResults.__init__(self, model, params, predy, w)
self.offset = model.offset
if w is not None:
Expand All @@ -616,6 +626,7 @@ def __init__(self, model, params, predy, S, CCT, influ, tr_STS=None,
self.influ = influ
self.CCT = self.cov_params(CCT, model.exog_scale)
self._cache = {}
self.name_x=name_x

@cache_readonly
def W(self):
Expand Down Expand Up @@ -1265,10 +1276,10 @@ def summary(self, as_str: bool = False) -> Optional[str]:
optional GWR summary string if `as_str` is True
"""
summary = summaryModel(self) + summaryGLM(self) + summaryGWR(self)

if as_str:
return summary

print(summary)
return None

Expand Down Expand Up @@ -1399,6 +1410,9 @@ class MGWR(GWR):
hat matrices R (n,n,k) and model hat matrix S (n,n).
False (default) for computing MGWR inference on the fly.

name_x : list of strings
Names of independent variables for use in output

Attributes
----------
coords : array-like
Expand Down Expand Up @@ -1475,6 +1489,9 @@ class MGWR(GWR):
observations from each calibration point: one for each
covariate (k)

name_x : list of strings
Names of independent variables for use in output

Examples
--------

Expand Down Expand Up @@ -1504,7 +1521,7 @@ class MGWR(GWR):

def __init__(self, coords, y, X, selector, sigma2_v1=True,
kernel='bisquare', fixed=False, constant=True,
spherical=False, hat_matrix=False):
spherical=False, hat_matrix=False, name_x=None):
"""
Initialize class
"""
Expand All @@ -1526,6 +1543,7 @@ def __init__(self, coords, y, X, selector, sigma2_v1=True,
self.exog_resid = None
self.exog_scale = None
self_fit_params = None
self.name_x = name_x

def _chunk_compute_R(self, chunk_id=0):
"""
Expand Down Expand Up @@ -1628,7 +1646,7 @@ def tqdm(x, total=0,
R = np.hstack(rslt_list[2])
else:
R = None
return MGWRResults(self, params, predy, CCT, ENP_j, w, R)
return MGWRResults(self, params, predy, CCT, ENP_j, w, R, self.name_x)


def exact_fit(self):
Expand Down Expand Up @@ -1713,6 +1731,9 @@ class MGWRResults(GWRResults):
n*1, final weight used for iteratively re-weighted least
sqaures; default is None

name_x : list of strings
Names of independent variables for use in output

Attributes
----------
model : GWR Object
Expand Down Expand Up @@ -1850,7 +1871,7 @@ class MGWRResults(GWRResults):

"""

def __init__(self, model, params, predy, CCT, ENP_j, w, R):
def __init__(self, model, params, predy, CCT, ENP_j, w, R, x_name=None):
"""
Initialize class
"""
Expand All @@ -1860,6 +1881,7 @@ def __init__(self, model, params, predy, CCT, ENP_j, w, R):
if model.hat_matrix:
self.S = np.sum(self.R, axis=2)
self.predy = predy
self.x_name = x_name

@cache_readonly
def tr_S(self):
Expand Down Expand Up @@ -2150,9 +2172,9 @@ def summary(self, as_str: bool=False) -> Optional[str]:
optional MGWR summary string if `as_str` is True
"""
summary = summaryModel(self) + summaryGLM(self) + summaryMGWR(self)

if as_str:
return summary

print(summary)
return
29 changes: 23 additions & 6 deletions mgwr/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ def summaryModel(self):

def summaryGLM(self):

XNames = ["X" + str(i) for i in range(self.k)]
if self.name_x is not None:
XNames = list(self.name_x)
if len(XNames) < self.k:
XNames = ["Intercept"] + XNames
else:
XNames = ["X" + str(i) for i in range(self.k)]
glm_rslt = GLM(self.model.y, self.model.X, constant=False,
family=self.family).fit()

Expand Down Expand Up @@ -47,14 +52,20 @@ def summaryGLM(self):
'-' * 10, '-' * 10)
for i in range(self.k):
summary += "%-31s %10.3f %10.3f %10.3f %10.3f\n" % (
XNames[i], glm_rslt.params[i], glm_rslt.bse[i],
XNames[i][:30], glm_rslt.params[i], glm_rslt.bse[i],
glm_rslt.tvalues[i], glm_rslt.pvalues[i])
summary += "\n"
return summary


def summaryGWR(self):
XNames = ["X" + str(i) for i in range(self.k)]
if self.name_x is not None:
XNames = list(self.name_x)
if len(XNames) < self.k:
XNames = ["Intercept"] + XNames

else:
XNames = ["X" + str(i) for i in range(self.k)]

summary = "%s\n" % ('Geographically Weighted Regression (GWR) Results')
summary += '-' * 75 + '\n'
Expand Down Expand Up @@ -111,7 +122,7 @@ def summaryGWR(self):
'-' * 20, '-' * 10, '-' * 10, '-' * 10, '-' * 10, '-' * 10)
for i in range(self.k):
summary += "%-20s %10.3f %10.3f %10.3f %10.3f %10.3f\n" % (
XNames[i], np.mean(self.params[:, i]), np.std(self.params[:, i]),
XNames[i][:20], np.mean(self.params[:, i]), np.std(self.params[:, i]),
np.min(self.params[:, i]), np.median(self.params[:, i]),
np.max(self.params[:, i]))

Expand All @@ -122,7 +133,13 @@ def summaryGWR(self):

def summaryMGWR(self):

XNames = ["X" + str(i) for i in range(self.k)]
if self.name_x is not None:
XNames = list(self.name_x)
if len(XNames) < self.k:
XNames = ["Intercept"] + XNames

else:
XNames = ["X" + str(i) for i in range(self.k)]

summary = ''
summary += "%s\n" % (
Expand Down Expand Up @@ -182,7 +199,7 @@ def summaryMGWR(self):
'-' * 20, '-' * 10, '-' * 10, '-' * 10, '-' * 10, '-' * 10)
for i in range(self.k):
summary += "%-20s %10.3f %10.3f %10.3f %10.3f %10.3f\n" % (
XNames[i], np.mean(self.params[:, i]), np.std(self.params[:, i]),
XNames[i][:20], np.mean(self.params[:, i]), np.std(self.params[:, i]),
np.min(self.params[:, i]), np.median(self.params[:, i]),
np.max(self.params[:, i]))

Expand Down