Skip to content

Commit 8ae798d

Browse files
authored
Merge pull request #359 from martinfleis/missing
ENH: move moran_facet plotting from splot
2 parents 89e3ddd + 634e5c5 commit 8ae798d

File tree

4 files changed

+133
-1
lines changed

4 files changed

+133
-1
lines changed

docs/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ Moran Statistics
104104
esda.Moran_Local_BV
105105
esda.Moran_Rate
106106
esda.Moran_Local_Rate
107+
esda.plot_moran_facet
107108

108109

109110
Shape Statistics

esda/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
Moran_Local_BV,
3535
Moran_Local_Rate,
3636
Moran_Rate,
37+
plot_moran_facet,
3738
)
3839
from .silhouettes import boundary_silhouette, path_silhouette # noqa F401
3940
from .smaup import Smaup # noqa F401

esda/moran.py

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"Levi John Wolf <[email protected]>"
1010
)
1111

12-
from warnings import simplefilter, warn
12+
from warnings import simplefilter
1313

1414
import numpy as np
1515
import pandas as pd
@@ -32,6 +32,7 @@
3232
"Moran_Local_BV",
3333
"Moran_Rate",
3434
"Moran_Local_Rate",
35+
"plot_moran_facet",
3536
]
3637

3738
PERMUTATIONS = 999
@@ -784,6 +785,115 @@ def _Moran_BV_Matrix_array(variables, w, permutations=0, varnames=None): # noqa
784785
return results
785786

786787

788+
def plot_moran_facet(
789+
moran_matrix,
790+
figsize=(16, 12),
791+
scatter_bv_kwds=None,
792+
fitline_bv_kwds=None,
793+
scatter_glob_kwds=dict(color="#737373"),
794+
fitline_glob_kwds=None,
795+
):
796+
"""
797+
Moran Facet visualization.
798+
799+
A matrix containing bivariate Moran plots between all pairs of variables present in
800+
the ``moran_matrix`` dictionary. On the diagonal contains global Moran plot.
801+
802+
Parameters
803+
----------
804+
moran_matrix : dict
805+
Dictionary of Moran_BV objects returned by Moran_BV_matrix
806+
figsize : tuple, optional
807+
Size of the figure. Default is (16,12)
808+
scatter_bv_kwds : keyword arguments, optional
809+
Keywords used for creating and designing the scatter points of
810+
off-diagonal Moran_BV plots.
811+
Default =None.
812+
fitline_bv_kwds : keyword arguments, optional
813+
Keywords used for creating and designing the moran fitline of
814+
off-diagonal Moran_BV plots.
815+
Default =None.
816+
scatter_glob_kwds : keyword arguments, optional
817+
Keywords used for creating and designing the scatter points of
818+
diagonal Moran plots.
819+
Default =None.
820+
fitline_glob_kwds : keyword arguments, optional
821+
Keywords used for creating and designing the moran fitline of
822+
diagonal Moran plots.
823+
Default =None.
824+
825+
Returns
826+
-------
827+
ax : matplotlib Axes instance
828+
Axes in which the figure is plotted
829+
"""
830+
try:
831+
from matplotlib import pyplot as plt
832+
except ImportError as err:
833+
raise ImportError(
834+
"matplotlib must be installed to plot the simulation."
835+
) from err
836+
837+
nrows = int(np.sqrt(len(moran_matrix))) + 1
838+
ncols = nrows
839+
840+
fig, axarr = plt.subplots(nrows, ncols, figsize=figsize, sharey=True, sharex=True)
841+
fig.suptitle("Moran Facet")
842+
843+
for row in range(nrows):
844+
for col in range(ncols):
845+
if row == col:
846+
global_m = Moran(
847+
moran_matrix[row, (row + 1) % 4].zy,
848+
moran_matrix[row, (row + 1) % 4].w,
849+
)
850+
_scatterplot(
851+
global_m,
852+
crit_value=None,
853+
ax=axarr[row, col],
854+
scatter_kwds=scatter_glob_kwds,
855+
fitline_kwds=fitline_glob_kwds,
856+
)
857+
axarr[row, col].set_facecolor("#d9d9d9")
858+
else:
859+
_scatterplot(
860+
moran_matrix[row, col],
861+
bivariate=True,
862+
crit_value=None,
863+
ax=axarr[row, col],
864+
scatter_kwds=scatter_bv_kwds,
865+
fitline_kwds=fitline_bv_kwds,
866+
)
867+
868+
axarr[row, col].spines[["left", "right", "top", "bottom"]].set_visible(
869+
False
870+
)
871+
if row == nrows - 1:
872+
axarr[row, col].set_xlabel(
873+
str(moran_matrix[(col + 1) % 4, col].varnames["x"]).format(col)
874+
)
875+
axarr[row, col].spines["bottom"].set_visible(True)
876+
else:
877+
axarr[row, col].set_xlabel("")
878+
879+
if col == 0:
880+
axarr[row, col].set_ylabel(
881+
(
882+
"Spatial Lag of "
883+
+ str(moran_matrix[row, (row + 1) % 4].varnames["y"])
884+
).format(row)
885+
)
886+
axarr[row, col].spines["left"].set_visible(True)
887+
else:
888+
axarr[row, col].set_ylabel("")
889+
890+
axarr[row, col].set_title("")
891+
892+
plt.tight_layout()
893+
894+
return axarr
895+
896+
787897
class Moran_Rate(Moran): # noqa: N801
788898
"""
789899
Adjusted Moran's I Global Autocorrelation Statistic for Rate

esda/tests/test_moran.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,26 @@ def test_Moran_BV_matrix(self, w):
298298
np.testing.assert_allclose(res[(0, 1)].I, 0.19362610652874668)
299299
np.testing.assert_allclose(res[(3, 0)].I, 0.37701382542927858)
300300

301+
@parametrize_sids
302+
def test_plot_moran_facet(self, w):
303+
matrix = moran.Moran_BV_matrix(self.vars, w, varnames=self.names)
304+
axes = moran.plot_moran_facet(matrix)
305+
assert axes.shape == (4, 4)
306+
307+
assert axes[0][0].spines["left"].get_visible()
308+
assert not axes[0][0].spines["bottom"].get_visible()
309+
assert axes[3][0].spines["left"].get_visible()
310+
assert axes[3][0].spines["bottom"].get_visible()
311+
assert not axes[3][1].spines["left"].get_visible()
312+
assert axes[3][1].spines["bottom"].get_visible()
313+
assert not axes[1][1].spines["left"].get_visible()
314+
assert not axes[1][1].spines["bottom"].get_visible()
315+
316+
np.testing.assert_array_almost_equal(
317+
axes[1][1].get_facecolor(),
318+
(0.8509803921568627, 0.8509803921568627, 0.8509803921568627, 1.0),
319+
)
320+
301321

302322
class TestMoranLocal:
303323
def setup_method(self):

0 commit comments

Comments
 (0)