diff --git a/mgwr/gwr.py b/mgwr/gwr.py index a0614c8..b8c2252 100755 --- a/mgwr/gwr.py +++ b/mgwr/gwr.py @@ -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 @@ -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 """ @@ -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 @@ -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, @@ -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 @@ -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: @@ -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): @@ -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 @@ -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 @@ -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 -------- @@ -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 """ @@ -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): """ @@ -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): @@ -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 @@ -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 """ @@ -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): @@ -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 diff --git a/mgwr/summary.py b/mgwr/summary.py index d3b58e7..1822071 100755 --- a/mgwr/summary.py +++ b/mgwr/summary.py @@ -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() @@ -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' @@ -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])) @@ -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" % ( @@ -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]))