diff --git a/mgwr/summary.py b/mgwr/summary.py index 1822071..8eef5cb 100755 --- a/mgwr/summary.py +++ b/mgwr/summary.py @@ -4,27 +4,32 @@ from .diagnostics import get_AICc -def summaryModel(self): - summary = '=' * 75 + '\n' - summary += "%-54s %20s\n" % ('Model type', self.family.__class__.__name__) - summary += "%-60s %14d\n" % ('Number of observations:', self.n) - summary += "%-60s %14d\n\n" % ('Number of covariates:', self.k) +def summaryModel(self) -> str: + """Summary of model + + Returns: + str: print out the model summary information + """ + summary = f"{'=' * 75} \n" + summary += f"{'Model type':<54s} {self.family.__class__.__name__:20s}\n" + summary += f"{'Number of observations:':<60s} {self.n:14d}\n" + summary += f"{'Number of covariates:':<60s} {self.k:14d}\n\n" return summary -def summaryGLM(self): +def summaryGLM(self) -> str: + """Summary of GLM - 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)] + Returns: + str: print out the GLM summary information + """ + + XNames = [f"X{i}" for i in range(self.k)] glm_rslt = GLM(self.model.y, self.model.X, constant=False, family=self.family).fit() - summary = "%s\n" % ('Global Regression Results') - summary += '-' * 75 + '\n' + summary = "Global Regression Results\n" + summary += f"{'-' * 75} \n" if isinstance(self.family, Gaussian): summary += "%-62s %12.3f\n" % ('Residual sum of squares:', @@ -52,20 +57,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][:30], glm_rslt.params[i], glm_rslt.bse[i], + XNames[i], glm_rslt.params[i], glm_rslt.bse[i], glm_rslt.tvalues[i], glm_rslt.pvalues[i]) summary += "\n" return summary -def summaryGWR(self): - if self.name_x is not None: - XNames = list(self.name_x) - if len(XNames) < self.k: - XNames = ["Intercept"] + XNames +def summaryGWR(self) -> str: + """Summary of GWR - else: - XNames = ["X" + str(i) for i in range(self.k)] + Returns: + str: print out the GWR summary information + """ + + XNames = ["X" + str(i) for i in range(self.k)] summary = "%s\n" % ('Geographically Weighted Regression (GWR) Results') summary += '-' * 75 + '\n' @@ -122,7 +127,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][:20], np.mean(self.params[:, i]), np.std(self.params[:, i]), + XNames[i], 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])) @@ -131,15 +136,14 @@ def summaryGWR(self): return summary -def summaryMGWR(self): +def summaryMGWR(self) -> str: + """Summary of MGWR - if self.name_x is not None: - XNames = list(self.name_x) - if len(XNames) < self.k: - XNames = ["Intercept"] + XNames + Returns: + str: print out the MGWR summary information + """ - else: - XNames = ["X" + str(i) for i in range(self.k)] + XNames = ["X" + str(i) for i in range(self.k)] summary = '' summary += "%s\n" % ( @@ -199,9 +203,9 @@ 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][:20], np.mean(self.params[:, i]), np.std(self.params[:, i]), + XNames[i], 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])) summary += '=' * 75 + '\n' - return summary + return summary \ No newline at end of file diff --git a/mgwr/tests/test_gwr.py b/mgwr/tests/test_gwr.py index 6af7a07..68728c6 100644 --- a/mgwr/tests/test_gwr.py +++ b/mgwr/tests/test_gwr.py @@ -66,10 +66,10 @@ def test_BS_F(self): BIC = get_BIC(rslt) CV = get_CV(rslt) - self.assertAlmostEquals(np.floor(AICc), 894.0) - self.assertAlmostEquals(np.floor(AIC), 890.0) - self.assertAlmostEquals(np.floor(BIC), 944.0) - self.assertAlmostEquals(np.round(CV, 2), 18.25) + self.assertAlmostEqual(np.floor(AICc), 894.0) + self.assertAlmostEqual(np.floor(AIC), 890.0) + self.assertAlmostEqual(np.floor(BIC), 944.0) + self.assertAlmostEqual(np.round(CV, 2), 18.25) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-04) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-04) @@ -135,12 +135,12 @@ def test_BS_NN(self): np.testing.assert_allclose( adj_alpha, np.array([0.02034978, 0.01017489, 0.0002035]), rtol=1e-04) - self.assertAlmostEquals(critical_t, 2.6011011542649394) - self.assertAlmostEquals(np.around(R2, 4), 0.5924) - self.assertAlmostEquals(np.floor(AICc), 896.0) - self.assertAlmostEquals(np.floor(AIC), 892.0) - self.assertAlmostEquals(np.floor(BIC), 941.0) - self.assertAlmostEquals(np.around(CV, 2), 19.19) + self.assertAlmostEqual(critical_t, 2.6011011542649394) + self.assertAlmostEqual(np.around(R2, 4), 0.5924) + self.assertAlmostEqual(np.floor(AICc), 896.0) + self.assertAlmostEqual(np.floor(AIC), 892.0) + self.assertAlmostEqual(np.floor(BIC), 941.0) + self.assertAlmostEqual(np.around(CV, 2), 19.19) np.testing.assert_allclose(corr1, corr2, rtol=1e-04) np.testing.assert_allclose(vif1, vif2, rtol=1e-04) np.testing.assert_allclose(cn1, cn2, rtol=1e-04) @@ -202,10 +202,10 @@ def test_GS_F(self): BIC = get_BIC(rslt) CV = get_CV(rslt) - self.assertAlmostEquals(np.floor(AICc), 895.0) - self.assertAlmostEquals(np.floor(AIC), 890.0) - self.assertAlmostEquals(np.floor(BIC), 943.0) - self.assertAlmostEquals(np.around(CV, 2), 18.21) + self.assertAlmostEqual(np.floor(AICc), 895.0) + self.assertAlmostEqual(np.floor(AIC), 890.0) + self.assertAlmostEqual(np.floor(BIC), 943.0) + self.assertAlmostEqual(np.around(CV, 2), 18.21) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-04) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-04) @@ -254,10 +254,10 @@ def test_GS_NN(self): BIC = get_BIC(rslt) CV = get_CV(rslt) - self.assertAlmostEquals(np.floor(AICc), 896.0) - self.assertAlmostEquals(np.floor(AIC), 894.0) - self.assertAlmostEquals(np.floor(BIC), 922.0) - self.assertAlmostEquals(np.around(CV, 2), 17.91) + self.assertAlmostEqual(np.floor(AICc), 896.0) + self.assertAlmostEqual(np.floor(AIC), 894.0) + self.assertAlmostEqual(np.floor(BIC), 922.0) + self.assertAlmostEqual(np.around(CV, 2), 17.91) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-04) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-04) @@ -473,11 +473,11 @@ def test_BS_NN_longlat(self): CV = get_CV(rslt) R2 = rslt.R2 - self.assertAlmostEquals(np.around(R2, 4), 0.5921) - self.assertAlmostEquals(np.floor(AICc), 896.0) - self.assertAlmostEquals(np.floor(AIC), 892.0) - self.assertAlmostEquals(np.floor(BIC), 941.0) - self.assertAlmostEquals(np.around(CV, 2), 19.11) + self.assertAlmostEqual(np.around(R2, 4), 0.5921) + self.assertAlmostEqual(np.floor(AICc), 896.0) + self.assertAlmostEqual(np.floor(AIC), 892.0) + self.assertAlmostEqual(np.floor(BIC), 941.0) + self.assertAlmostEqual(np.around(CV, 2), 19.11) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-04) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-04) @@ -557,9 +557,9 @@ def test_BS_F(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 13294.0) - self.assertAlmostEquals(np.floor(AIC), 13247.0) - self.assertAlmostEquals(np.floor(BIC), 13485.0) + self.assertAlmostEqual(np.floor(AICc), 13294.0) + self.assertAlmostEqual(np.floor(AIC), 13247.0) + self.assertAlmostEqual(np.floor(BIC), 13485.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-05) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-03) @@ -607,10 +607,10 @@ def test_BS_NN(self): BIC = get_BIC(rslt) D2 = rslt.D2 - self.assertAlmostEquals(np.floor(AICc), 13285) - self.assertAlmostEquals(np.floor(AIC), 13259.0) - self.assertAlmostEquals(np.floor(BIC), 13442.0) - self.assertAlmostEquals(np.round(D2, 3), 0.747) + self.assertAlmostEqual(np.floor(AICc), 13285) + self.assertAlmostEqual(np.floor(AIC), 13259.0) + self.assertAlmostEqual(np.floor(BIC), 13442.0) + self.assertAlmostEqual(np.round(D2, 3), 0.747) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-02) @@ -659,10 +659,10 @@ def test_BS_NN_Offset(self): BIC = get_BIC(rslt) D2 = rslt.D2 - self.assertAlmostEquals(np.floor(AICc), 367.0) - self.assertAlmostEquals(np.floor(AIC), 361.0) - self.assertAlmostEquals(np.floor(BIC), 451.0) - self.assertAlmostEquals(np.round(D2, 3), 0.676) + self.assertAlmostEqual(np.floor(AICc), 367.0) + self.assertAlmostEqual(np.floor(AIC), 361.0) + self.assertAlmostEqual(np.floor(BIC), 451.0) + self.assertAlmostEqual(np.round(D2, 3), 0.676) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-02, atol=1e-02) @@ -724,9 +724,9 @@ def test_GS_F(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 11283.0) - self.assertAlmostEquals(np.floor(AIC), 11211.0) - self.assertAlmostEquals(np.floor(BIC), 11497.0) + self.assertAlmostEqual(np.floor(AICc), 11283.0) + self.assertAlmostEqual(np.floor(AIC), 11211.0) + self.assertAlmostEqual(np.floor(BIC), 11497.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-03) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-02) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-02) @@ -772,9 +772,9 @@ def test_GS_NN(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 21070.0) - self.assertAlmostEquals(np.floor(AIC), 21069.0) - self.assertAlmostEquals(np.floor(BIC), 21111.0) + self.assertAlmostEqual(np.floor(AICc), 21070.0) + self.assertAlmostEqual(np.floor(AIC), 21069.0) + self.assertAlmostEqual(np.floor(BIC), 21111.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-02) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-02) @@ -859,9 +859,9 @@ def test_BS_F(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 275.0) - self.assertAlmostEquals(np.floor(AIC), 271.0) - self.assertAlmostEquals(np.floor(BIC), 349.0) + self.assertAlmostEqual(np.floor(AICc), 275.0) + self.assertAlmostEqual(np.floor(AIC), 271.0) + self.assertAlmostEqual(np.floor(BIC), 349.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-00) @@ -923,10 +923,10 @@ def test_BS_NN(self): BIC = get_BIC(rslt) D2 = rslt.D2 - self.assertAlmostEquals(np.floor(AICc), 277.0) - self.assertAlmostEquals(np.floor(AIC), 271.0) - self.assertAlmostEquals(np.floor(BIC), 358.0) - self.assertAlmostEquals(np.round(D2, 3), 0.319) + self.assertAlmostEqual(np.floor(AICc), 277.0) + self.assertAlmostEqual(np.floor(AIC), 271.0) + self.assertAlmostEqual(np.floor(BIC), 358.0) + self.assertAlmostEqual(np.round(D2, 3), 0.319) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) @@ -989,9 +989,9 @@ def test_GS_F(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 276.0) - self.assertAlmostEquals(np.floor(AIC), 272.0) - self.assertAlmostEquals(np.floor(BIC), 341.0) + self.assertAlmostEqual(np.floor(AICc), 276.0) + self.assertAlmostEqual(np.floor(AIC), 272.0) + self.assertAlmostEqual(np.floor(BIC), 341.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-00) @@ -1052,9 +1052,9 @@ def test_GS_NN(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 276.0) - self.assertAlmostEquals(np.floor(AIC), 273.0) - self.assertAlmostEquals(np.floor(BIC), 331.0) + self.assertAlmostEqual(np.floor(AICc), 276.0) + self.assertAlmostEqual(np.floor(AIC), 273.0) + self.assertAlmostEqual(np.floor(BIC), 331.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-00) diff --git a/mgwr/tests/test_parallel.py b/mgwr/tests/test_parallel.py index a485cdf..fb3b2b6 100644 --- a/mgwr/tests/test_parallel.py +++ b/mgwr/tests/test_parallel.py @@ -84,12 +84,12 @@ def test_BS_NN_Parallel(self): np.testing.assert_allclose( adj_alpha, np.array([0.02034978, 0.01017489, 0.0002035]), rtol=1e-04) - self.assertAlmostEquals(critical_t, 2.6011011542649394) - self.assertAlmostEquals(np.around(R2, 4), 0.5924) - self.assertAlmostEquals(np.floor(AICc), 896.0) - self.assertAlmostEquals(np.floor(AIC), 892.0) - self.assertAlmostEquals(np.floor(BIC), 941.0) - self.assertAlmostEquals(np.around(CV, 2), 19.19) + self.assertAlmostEqual(critical_t, 2.6011011542649394) + self.assertAlmostEqual(np.around(R2, 4), 0.5924) + self.assertAlmostEqual(np.floor(AICc), 896.0) + self.assertAlmostEqual(np.floor(AIC), 892.0) + self.assertAlmostEqual(np.floor(BIC), 941.0) + self.assertAlmostEqual(np.around(CV, 2), 19.19) np.testing.assert_allclose(corr1, corr2, rtol=1e-04) np.testing.assert_allclose(vif1, vif2, rtol=1e-04) np.testing.assert_allclose(cn1, cn2, rtol=1e-04) @@ -152,10 +152,10 @@ def test_GS_F_Parallel(self): BIC = get_BIC(rslt) CV = get_CV(rslt) - self.assertAlmostEquals(np.floor(AICc), 895.0) - self.assertAlmostEquals(np.floor(AIC), 890.0) - self.assertAlmostEquals(np.floor(BIC), 943.0) - self.assertAlmostEquals(np.around(CV, 2), 18.21) + self.assertAlmostEqual(np.floor(AICc), 895.0) + self.assertAlmostEqual(np.floor(AIC), 890.0) + self.assertAlmostEqual(np.floor(BIC), 943.0) + self.assertAlmostEqual(np.around(CV, 2), 18.21) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-04) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-04) @@ -364,11 +364,11 @@ def test_BS_NN_longlat_Parallel(self): CV = get_CV(rslt) R2 = rslt.R2 - self.assertAlmostEquals(np.around(R2, 4), 0.5921) - self.assertAlmostEquals(np.floor(AICc), 896.0) - self.assertAlmostEquals(np.floor(AIC), 892.0) - self.assertAlmostEquals(np.floor(BIC), 941.0) - self.assertAlmostEquals(np.around(CV, 2), 19.11) + self.assertAlmostEqual(np.around(R2, 4), 0.5921) + self.assertAlmostEqual(np.floor(AICc), 896.0) + self.assertAlmostEqual(np.floor(AIC), 892.0) + self.assertAlmostEqual(np.floor(BIC), 941.0) + self.assertAlmostEqual(np.around(CV, 2), 19.11) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-04) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-04) @@ -449,9 +449,9 @@ def test_BS_F_Parallel(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 13294.0) - self.assertAlmostEquals(np.floor(AIC), 13247.0) - self.assertAlmostEquals(np.floor(BIC), 13485.0) + self.assertAlmostEqual(np.floor(AICc), 13294.0) + self.assertAlmostEqual(np.floor(AIC), 13247.0) + self.assertAlmostEqual(np.floor(BIC), 13485.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-05) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-03) @@ -500,10 +500,10 @@ def test_BS_NN(self): BIC = get_BIC(rslt) D2 = rslt.D2 - self.assertAlmostEquals(np.floor(AICc), 13285) - self.assertAlmostEquals(np.floor(AIC), 13259.0) - self.assertAlmostEquals(np.floor(BIC), 13442.0) - self.assertAlmostEquals(np.round(D2, 3), 0.747) + self.assertAlmostEqual(np.floor(AICc), 13285) + self.assertAlmostEqual(np.floor(AIC), 13259.0) + self.assertAlmostEqual(np.floor(BIC), 13442.0) + self.assertAlmostEqual(np.round(D2, 3), 0.747) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-02) @@ -553,10 +553,10 @@ def test_BS_NN_Offset_Parallel(self): BIC = get_BIC(rslt) D2 = rslt.D2 - self.assertAlmostEquals(np.floor(AICc), 367.0) - self.assertAlmostEquals(np.floor(AIC), 361.0) - self.assertAlmostEquals(np.floor(BIC), 451.0) - self.assertAlmostEquals(np.round(D2, 3), 0.676) + self.assertAlmostEqual(np.floor(AICc), 367.0) + self.assertAlmostEqual(np.floor(AIC), 361.0) + self.assertAlmostEqual(np.floor(BIC), 451.0) + self.assertAlmostEqual(np.round(D2, 3), 0.676) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-02, atol=1e-02) @@ -619,9 +619,9 @@ def test_GS_F_Parallel(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 11283.0) - self.assertAlmostEquals(np.floor(AIC), 11211.0) - self.assertAlmostEquals(np.floor(BIC), 11497.0) + self.assertAlmostEqual(np.floor(AICc), 11283.0) + self.assertAlmostEqual(np.floor(AIC), 11211.0) + self.assertAlmostEqual(np.floor(BIC), 11497.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-03) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-02) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-02) @@ -668,9 +668,9 @@ def test_GS_NN_Parallel(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 21070.0) - self.assertAlmostEquals(np.floor(AIC), 21069.0) - self.assertAlmostEquals(np.floor(BIC), 21111.0) + self.assertAlmostEqual(np.floor(AICc), 21070.0) + self.assertAlmostEqual(np.floor(AIC), 21069.0) + self.assertAlmostEqual(np.floor(BIC), 21111.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-04) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-02) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-02) @@ -756,9 +756,9 @@ def test_BS_F_Parallel(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 275.0) - self.assertAlmostEquals(np.floor(AIC), 271.0) - self.assertAlmostEquals(np.floor(BIC), 349.0) + self.assertAlmostEqual(np.floor(AICc), 275.0) + self.assertAlmostEqual(np.floor(AIC), 271.0) + self.assertAlmostEqual(np.floor(BIC), 349.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-00) @@ -821,10 +821,10 @@ def test_BS_NN_Parallel(self): BIC = get_BIC(rslt) D2 = rslt.D2 - self.assertAlmostEquals(np.floor(AICc), 277.0) - self.assertAlmostEquals(np.floor(AIC), 271.0) - self.assertAlmostEquals(np.floor(BIC), 358.0) - self.assertAlmostEquals(np.round(D2, 3), 0.319) + self.assertAlmostEqual(np.floor(AICc), 277.0) + self.assertAlmostEqual(np.floor(AIC), 271.0) + self.assertAlmostEqual(np.floor(BIC), 358.0) + self.assertAlmostEqual(np.round(D2, 3), 0.319) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) @@ -888,9 +888,9 @@ def test_GS_F_Parallel(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 276.0) - self.assertAlmostEquals(np.floor(AIC), 272.0) - self.assertAlmostEquals(np.floor(BIC), 341.0) + self.assertAlmostEqual(np.floor(AICc), 276.0) + self.assertAlmostEqual(np.floor(AIC), 272.0) + self.assertAlmostEqual(np.floor(BIC), 341.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-00) @@ -952,9 +952,9 @@ def test_GS_NN_Parallel(self): AIC = get_AIC(rslt) BIC = get_BIC(rslt) - self.assertAlmostEquals(np.floor(AICc), 276.0) - self.assertAlmostEquals(np.floor(AIC), 273.0) - self.assertAlmostEquals(np.floor(BIC), 331.0) + self.assertAlmostEqual(np.floor(AICc), 276.0) + self.assertAlmostEqual(np.floor(AIC), 273.0) + self.assertAlmostEqual(np.floor(BIC), 331.0) np.testing.assert_allclose(est_Int, rslt.params[:, 0], rtol=1e-00) np.testing.assert_allclose(se_Int, rslt.bse[:, 0], rtol=1e-00) np.testing.assert_allclose(t_Int, rslt.tvalues[:, 0], rtol=1e-00) diff --git a/mgwr/utils.py b/mgwr/utils.py index 39f4a92..0d2097f 100755 --- a/mgwr/utils.py +++ b/mgwr/utils.py @@ -1,34 +1,44 @@ import numpy as np from libpysal.common import requires +from matplotlib.colors import LinearSegmentedColormap +import pandas as pd @requires('matplotlib') -def shift_colormap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'): - ''' - Function to offset the "center" of a colormap. Useful for - data with a negative min and positive max and you want the - middle of the colormap's dynamic range to be at zero - - Parameters - ---------- - cmap : The matplotlib colormap to be altered - start : Offset from lowest point in the colormap's range. - Defaults to 0.0 (no lower ofset). Should be between - 0.0 and `midpoint`. - midpoint : The new center of the colormap. Defaults to - 0.5 (no shift). Should be between 0.0 and 1.0. In - general, this should be 1 - vmax/(vmax + abs(vmin)) - For example if your data range from -15.0 to +5.0 and - you want the center of the colormap at 0.0, `midpoint` - should be set to 1 - 5/(5 + 15)) or 0.75 - stop : Offset from highets point in the colormap's range. - Defaults to 1.0 (no upper ofset). Should be between - `midpoint` and 1.0. - - Returns - ------- - new_cmap : A new colormap that has been shifted. - ''' +def shift_colormap(cmap: LinearSegmentedColormap, + start: float = 0, + midpoint: float = 0.5, + stop: float = 1.0, + name: str = 'shiftedcmap') -> LinearSegmentedColormap: + + """Function to offset the "center" of a colormap. + Useful for data with a negative min and positive max + and you want the middle of the colormap's dynamic range to be at zero + + Args: + cmap (LinearSegmentedColormap): The matplotlib colormap to be altered + start (float): Offset from lowest point in the colormap's range. + Defaults to 0.0 (no lower ofset). + Should be between 0.0 and `midpoint`. + midpoint (float): The new center of the colormap. Defaults to 0.5 (no shift). Should be between 0.0 and 1.0. + In general, this should be 1 - vmax/(vmax + abs(vmin)) + For example if your data range from -15.0 to +5.0 and + you want the center of the colormap at 0.0, `midpoint` + should be set to 1 - 5/(5 + 15)) or 0.75 + stop (float): Offset from highets point in the colormap's range. + Defaults to 1.0 (no upper ofset). Should be between + `midpoint` and 1.0. + + Returns: + LinearSegmentedColormap: A new colormap that has been shifted. + + Examples: + >>> import numpy as np + >>> import matplotlib.pyplot as plt + >>> from mgwr.utils import shift_colormap + >>> cmap = plt.cm.seismic + >>> cmap = shift_colormap(cmap, start=0, midpoint=1 - 5/(5 + 15), stop=1, name='shiftedcmap') + """ import matplotlib as mpl import matplotlib.pyplot as plt @@ -59,61 +69,97 @@ def shift_colormap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'): @requires('matplotlib') -def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=100): +def truncate_colormap(cmap: LinearSegmentedColormap, + min_val: float = 0.0, + max_val: float = 1.0, + n: int = 100) -> LinearSegmentedColormap: ''' Function to truncate a colormap by selecting a subset of the original colormap's values - Parameters - ---------- - cmap : Mmatplotlib colormap to be altered - minval : Minimum value of the original colormap to include in the truncated colormap - maxval : Maximum value of the original colormap to include in the truncated colormap - n : Number of intervals between the min and max values for the gradient of the truncated colormap - - Returns - ------- - new_cmap : A new colormap that has been shifted. + Args: + cmap (LinearSegmentedColormap) : Matplotlib colormap to be altered + min_val (float) : Minimum value of the original colormap to include in the truncated colormap + max_val (float) : Maximum value of the original colormap to include in the truncated colormap + n (int) : Number of intervals between the min and max values for the gradient of the truncated colormap + + Returns: + new_camap (LinearSegmentedColormap) : A new colormap that has been truncated. + + Examples: + >>> import numpy as np + >>> import matplotlib.pyplot as plt + >>> from mgwr.utils import truncate_colormap + >>> cmap = plt.cm.seismic + >>> cmap = truncate_colormap(cmap, min_val=0.0, max_val=0.5, n=100) + ''' import matplotlib as mpl new_cmap = mpl.colors.LinearSegmentedColormap.from_list( - 'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval), - cmap(np.linspace(minval, maxval, n))) + 'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=min_val, b=max_val), + cmap(np.linspace(min_val, max_val, n))) return new_cmap @requires('matplotlib') @requires('geopandas') -def compare_surfaces(data, var1, var2, gwr_t, gwr_bw, mgwr_t, mgwr_bw, name, - kwargs1, kwargs2, savefig=None): +def compare_surfaces(data: pd.DataFrame, + var1: str, + var2: str, + gwr_t: str, + gwr_bw: float, + mgwr_t: str, + mgwr_bw: float, + name: str, + kwargs1, + kwargs2, + savefig: str = None) -> None: ''' Function that creates comparative visualization of GWR and MGWR surfaces. - Parameters - ---------- - data : pandas or geopandas Dataframe - gwr/mgwr results - var1 : string - name of gwr parameter estimate column in frame - var2 : string - name of mgwr parameter estimate column in frame - gwr_t : string - name of gwr t-values column in frame associated with var1 - gwr_bw : float - bandwidth for gwr model for var1 - mgwr_t : string - name of mgwr t-values column in frame associated with var2 - mgwr_bw: float - bandwidth for mgwr model for var2 - name : string - common variable name to use for title - kwargs1: - additional plotting arguments for gwr surface - kwargs2: - additional plotting arguments for mgwr surface - savefig: string, optional - path to save the figure. Default is None. Not to save figure. + Args: + data (pandas or geopandas Dataframe) : gwr/mgwr results + var1 (string) : name of gwr parameter estimate column in frame + var2 (string) : name of mgwr parameter estimate column in frame + gwr_t (string) : name of gwr t-values column in frame associated with var1 + gwr_bw (float) : bandwidth for gwr model for var1 + mgwr_t (string) : name of mgwr t-values column in frame associated with var2 + mgwr_bw (float) : bandwidth for mgwr model for var2 + name (string) : common variable name to use for title + kwargs1 : additional plotting arguments for gwr surface + kwargs2 : additional plotting arguments for mgwr surface + savefig (string, optional) : path to save the figure. Default is None. Not to save figure. + + Returns: + None + + Examples: + >>> import numpy as np + >>> import matplotlib.pyplot as plt + >>> from mgwr.utils import compare_surfaces + >>> from mgwr.gwr import GWR, MGWR + >>> from libpysal.examples import load_example + >>> from libpysal import io + >>> from libpysal.weights import Queen + + >>> data = io.open(io.get_path('GData_utm.csv')) + >>> coords = list(zip(data['X'].values, data['Y'].values)) + >>> y = data['PctBach'].values.reshape((-1,1)) + >>> X = data[['PctFB', 'PctBlack', 'PctRural']].values + >>> bw = 100 + + >>> gwr_selector = Sel_BW(coords, y, X, kernel='gaussian') + >>> gwr_bw = gwr_selector.search(bw_min=25) + >>> gwr_model = GWR(coords, y, X, gwr_bw, kernel='gaussian') + >>> gwr_results = gwr_model.fit() + + >>> mgwr_selector = Sel_BW(coords, y, X, kernel='gaussian') + >>> mgwr_bw = mgwr_selector.search(bw_min=25) + >>> mgwr_model = MGWR(coords, y, X, mgwr_bw, kernel='gaussian') + >>> mgwr_results = mgwr_model.fit() + >>> compare_surfaces(data, 'PctFB', 'PctFB', gwr_results.tvalues, gwr_bw, mgwr_results.tvalues, mgwr_bw, 'PctFB', {}, {}, savefig='compare_surfaces.png') + ''' import matplotlib.pyplot as plt import geopandas as gp @@ -126,10 +172,10 @@ def compare_surfaces(data, var1, var2, gwr_t, gwr_bw, mgwr_t, mgwr_bw, name, ax1.set_title('MGWR ' + name + ' Surface (BW: ' + str(mgwr_bw) + ')', fontsize=40) - #Set color map + # Set color map cmap = plt.cm.seismic - #Find min and max values of the two combined datasets + # Find min and max values of the two combined datasets gwr_min = data[var1].min() gwr_max = data[var1].max() mgwr_min = data[var2].min() @@ -137,32 +183,34 @@ def compare_surfaces(data, var1, var2, gwr_t, gwr_bw, mgwr_t, mgwr_bw, name, vmin = np.min([gwr_min, mgwr_min]) vmax = np.max([gwr_max, mgwr_max]) - #If all values are negative use the negative half of the colormap + # If all values are negative use the negative half of the colormap if (vmin < 0) & (vmax < 0): cmap = truncate_colormap(cmap, 0.0, 0.5) - #If all values are positive use the positive half of the colormap + + # If all values are positive use the positive half of the colormap elif (vmin > 0) & (vmax > 0): cmap = truncate_colormap(cmap, 0.5, 1.0) - #Otherwise, there are positive and negative values so the colormap so zero is the midpoint + + # Otherwise, there are positive and negative values so the colormap so zero is the midpoint else: cmap = shift_colormap(cmap, start=0.0, midpoint=1 - vmax / (vmax + abs(vmin)), stop=1.) - #Create scalar mappable for colorbar and stretch colormap across range of data values + # Create scalar mappable for colorbar and stretch colormap across range of data values sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize( vmin=vmin, vmax=vmax)) - #Plot GWR parameters + # Plot GWR parameters data.plot(var1, cmap=sm.cmap, ax=ax0, vmin=vmin, vmax=vmax, **kwargs1) if (gwr_t == 0).any(): data[gwr_t == 0].plot(color='lightgrey', ax=ax0, **kwargs2) - #Plot MGWR parameters + # Plot MGWR parameters data.plot(var2, cmap=sm.cmap, ax=ax1, vmin=vmin, vmax=vmax, **kwargs1) if (mgwr_t == 0).any(): data[mgwr_t == 0].plot(color='lightgrey', ax=ax1, **kwargs2) - #Set figure options and plot + # Set figure options and plot fig.tight_layout() fig.subplots_adjust(right=0.9) cax = fig.add_axes([0.92, 0.14, 0.03, 0.75]) @@ -175,4 +223,4 @@ def compare_surfaces(data, var1, var2, gwr_t, gwr_bw, mgwr_t, mgwr_bw, name, ax1.get_yaxis().set_visible(False) if savefig is not None: plt.savefig(savefig) - plt.show() + plt.show() \ No newline at end of file