From 808f97897575a0dac68435ec2dcfaf579d32a3ce Mon Sep 17 00:00:00 2001 From: eli knaap Date: Tue, 18 Jun 2024 21:20:19 -0700 Subject: [PATCH 01/13] plot histogram --- mapclassify/classifiers.py | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 515a0dc0..0d28c757 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1123,6 +1123,52 @@ def plot( plt.savefig(file_name, dpi=dpi) return f, ax + def plot_histogram( + self, hist_kwargs=None, hist_color="dodgerblue", linecolor="black", ax=None + ): + """Plot histogram of `y` with bin values superimposed + + Parameters + ---------- + hist_kwargs : dict, optional + additional keyword arguments passed to pandas.Series.histogram, by default None + hist_color : str, optional + hue to color bars of the histogram, by default "dodgerblue" + linecolor : str, optional + color of the lines demarcating each class bin, by default "black" + ax : matplotlib.Axes, optional + axes object to plot onto, by default None + + Returns + ------- + matplotlib.Axes + an Axes object with histogram and class bins + + Raises + ------ + ImportError + depends on pandas and seaborn and rasies if not packages not present + """ + try: + import pandas as pd + import seaborn as sns + except ImportError as e: + raise ImportError from e( + "You must have pandas ans seaborn available to use this function" + ) + if hist_kwargs is None: + hist_kwargs = dict() + if 'color' not in hist_kwargs: + hist_kwargs['color'] = hist_color + series = pd.Series(self.y) + ax = series.plot(kind="hist", ax=ax, **hist_kwargs) + + lim = ax.get_ylim()[1] + for i in self.bins: + ax.vlines(i, 0, lim, color=linecolor) + sns.despine() + return ax + class HeadTailBreaks(MapClassifier): """ From 0e3b18ce337b527d0cf8a72c189a57bf03c8788c Mon Sep 17 00:00:00 2001 From: eli knaap Date: Tue, 18 Jun 2024 22:01:59 -0700 Subject: [PATCH 02/13] reorder args --- mapclassify/classifiers.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 0d28c757..5e918b92 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1124,20 +1124,21 @@ def plot( return f, ax def plot_histogram( - self, hist_kwargs=None, hist_color="dodgerblue", linecolor="black", ax=None + self, hist_color="dodgerblue", linecolor="black", ax=None, hist_kwargs=None ): """Plot histogram of `y` with bin values superimposed Parameters ---------- - hist_kwargs : dict, optional - additional keyword arguments passed to pandas.Series.histogram, by default None hist_color : str, optional hue to color bars of the histogram, by default "dodgerblue" linecolor : str, optional color of the lines demarcating each class bin, by default "black" ax : matplotlib.Axes, optional axes object to plot onto, by default None + hist_kwargs : dict, optional + additional keyword arguments passed to pandas.Series.histogram, by default + None Returns ------- From b8ad4e34950171d5e9e01ad58430e1d518172a2b Mon Sep 17 00:00:00 2001 From: eli knaap Date: Tue, 18 Jun 2024 22:14:20 -0700 Subject: [PATCH 03/13] despine optional; add comments --- mapclassify/classifiers.py | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 5e918b92..3bfec636 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1124,18 +1124,27 @@ def plot( return f, ax def plot_histogram( - self, hist_color="dodgerblue", linecolor="black", ax=None, hist_kwargs=None + self, + hist_color="dodgerblue", + linecolor="black", + ax=None, + despine=True, + hist_kwargs=None, ): """Plot histogram of `y` with bin values superimposed Parameters ---------- hist_color : str, optional - hue to color bars of the histogram, by default "dodgerblue" + hue to color bars of the histogram, by default "dodgerblue". This option + overrides the 'color' entry in `hist_kwargs` if specified. linecolor : str, optional color of the lines demarcating each class bin, by default "black" ax : matplotlib.Axes, optional axes object to plot onto, by default None + despine : bool, optional + If True, to use seaborn's despine function to remove top and right axes, + default is True hist_kwargs : dict, optional additional keyword arguments passed to pandas.Series.histogram, by default None @@ -1148,26 +1157,37 @@ def plot_histogram( Raises ------ ImportError - depends on pandas and seaborn and rasies if not packages not present + depends on pandas (and seaborn if despine=True) and rasies if not packages + not present """ try: import pandas as pd - import seaborn as sns except ImportError as e: raise ImportError from e( - "You must have pandas ans seaborn available to use this function" + "You must have pandas available to use this function" ) if hist_kwargs is None: hist_kwargs = dict() - if 'color' not in hist_kwargs: - hist_kwargs['color'] = hist_color + # override color in case specified explicitly and inside the dict + if "color" not in hist_kwargs: + hist_kwargs["color"] = hist_color + # plot `y` as a histogram series = pd.Series(self.y) ax = series.plot(kind="hist", ax=ax, **hist_kwargs) - + # get the top of the ax so we know how high to raise each class bar lim = ax.get_ylim()[1] + # plot upper limit of each bin for i in self.bins: ax.vlines(i, 0, lim, color=linecolor) - sns.despine() + # despine if specified + if despine: + try: + import seaborn as sns + sns.despine(ax=ax) + except ImportError as e: + raise ImportError from e( + "The seaborn package is required to use the despine option" + ) return ax From 01a0e5fdf044366c1c8533ea98f97b3a1fbdee07 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Tue, 18 Jun 2024 22:16:43 -0700 Subject: [PATCH 04/13] warn not raise if sns missing --- mapclassify/classifiers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 3bfec636..4eb73190 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1185,8 +1185,9 @@ def plot_histogram( import seaborn as sns sns.despine(ax=ax) except ImportError as e: - raise ImportError from e( - "The seaborn package is required to use the despine option" + warnings.warn( + "The seaborn package is required to use the despine option", + stacklevel=2, ) return ax From 3ad347d80db08275cde3fa570e3bc2a754ac277a Mon Sep 17 00:00:00 2001 From: eli knaap Date: Tue, 25 Jun 2024 23:22:56 -0700 Subject: [PATCH 05/13] martins improvements --- mapclassify/classifiers.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 4eb73190..17ada897 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1157,14 +1157,15 @@ def plot_histogram( Raises ------ ImportError - depends on pandas (and seaborn if despine=True) and rasies if not packages - not present + depends matplotlib and rasies if not installed """ try: - import pandas as pd + import matplotlib.pyplot as plt + if ax is None: + _, ax = plt.subplots() except ImportError as e: raise ImportError from e( - "You must have pandas available to use this function" + "You must have matplotlib available to use this function" ) if hist_kwargs is None: hist_kwargs = dict() @@ -1172,8 +1173,7 @@ def plot_histogram( if "color" not in hist_kwargs: hist_kwargs["color"] = hist_color # plot `y` as a histogram - series = pd.Series(self.y) - ax = series.plot(kind="hist", ax=ax, **hist_kwargs) + ax.hist(self.y, **hist_kwargs) # get the top of the ax so we know how high to raise each class bar lim = ax.get_ylim()[1] # plot upper limit of each bin @@ -1181,14 +1181,8 @@ def plot_histogram( ax.vlines(i, 0, lim, color=linecolor) # despine if specified if despine: - try: - import seaborn as sns - sns.despine(ax=ax) - except ImportError as e: - warnings.warn( - "The seaborn package is required to use the despine option", - stacklevel=2, - ) + ax.spines['right'].set_visible(False) + ax.spines['top'].set_visible(False) return ax From ab99136507cfd9549d2bf11d956a81c735342aee Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 08:49:19 -0700 Subject: [PATCH 06/13] simplify args --- mapclassify/classifiers.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 17ada897..3e4276a2 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1125,17 +1125,17 @@ def plot( def plot_histogram( self, - hist_color="dodgerblue", + color="dodgerblue", linecolor="black", ax=None, despine=True, - hist_kwargs=None, + **kwargs, ): """Plot histogram of `y` with bin values superimposed Parameters ---------- - hist_color : str, optional + color : str, optional hue to color bars of the histogram, by default "dodgerblue". This option overrides the 'color' entry in `hist_kwargs` if specified. linecolor : str, optional @@ -1145,7 +1145,7 @@ def plot_histogram( despine : bool, optional If True, to use seaborn's despine function to remove top and right axes, default is True - hist_kwargs : dict, optional + kwargs : dict, optional additional keyword arguments passed to pandas.Series.histogram, by default None @@ -1167,13 +1167,13 @@ def plot_histogram( raise ImportError from e( "You must have matplotlib available to use this function" ) - if hist_kwargs is None: - hist_kwargs = dict() + if kwargs is None: + kwargs = dict() # override color in case specified explicitly and inside the dict - if "color" not in hist_kwargs: - hist_kwargs["color"] = hist_color + if "color" not in kwargs: + kwargs["color"] = color # plot `y` as a histogram - ax.hist(self.y, **hist_kwargs) + ax.hist(self.y, **kwargs) # get the top of the ax so we know how high to raise each class bar lim = ax.get_ylim()[1] # plot upper limit of each bin From 69435b219c8fe98d342e13020d4e24790bf59441 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 09:12:58 -0700 Subject: [PATCH 07/13] mpl not pandas in docstring --- mapclassify/classifiers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 3e4276a2..38f2d665 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1146,7 +1146,7 @@ def plot_histogram( If True, to use seaborn's despine function to remove top and right axes, default is True kwargs : dict, optional - additional keyword arguments passed to pandas.Series.histogram, by default + additional keyword arguments passed to matplotlib.axes.Axes.hist, by default None Returns From c8de66c4f9f2903cc167da949826cf3084b213ec Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 12:01:25 -0700 Subject: [PATCH 08/13] linewidth --- mapclassify/classifiers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 38f2d665..e517b0bb 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1127,6 +1127,7 @@ def plot_histogram( self, color="dodgerblue", linecolor="black", + linewidth=None, ax=None, despine=True, **kwargs, @@ -1140,6 +1141,8 @@ def plot_histogram( overrides the 'color' entry in `hist_kwargs` if specified. linecolor : str, optional color of the lines demarcating each class bin, by default "black" + linewidth : int, optional + change the linewidth demarcating each class bin ax : matplotlib.Axes, optional axes object to plot onto, by default None despine : bool, optional @@ -1178,7 +1181,7 @@ def plot_histogram( lim = ax.get_ylim()[1] # plot upper limit of each bin for i in self.bins: - ax.vlines(i, 0, lim, color=linecolor) + ax.vlines(i, 0, lim, color=linecolor, linewidth=linewidth) # despine if specified if despine: ax.spines['right'].set_visible(False) From 976b4306b5c87960e6c7f65eb01838f9e40eacd0 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 15:08:56 -0700 Subject: [PATCH 09/13] add tests --- .../tests/baseline/test_histogram_plot.png | Bin 0 -> 8726 bytes .../baseline/test_histogram_plot_despine.png | Bin 0 -> 8787 bytes .../test_histogram_plot_linewidth.png | Bin 0 -> 8660 bytes mapclassify/tests/test_mapclassify.py | 20 ++++++++++++++++++ 4 files changed, 20 insertions(+) create mode 100644 mapclassify/tests/baseline/test_histogram_plot.png create mode 100644 mapclassify/tests/baseline/test_histogram_plot_despine.png create mode 100644 mapclassify/tests/baseline/test_histogram_plot_linewidth.png diff --git a/mapclassify/tests/baseline/test_histogram_plot.png b/mapclassify/tests/baseline/test_histogram_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..1c1274bcc278218fbcec6e6b7aa01bee3f063fbc GIT binary patch literal 8726 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 GXa5Ichld6L literal 0 HcmV?d00001 diff --git a/mapclassify/tests/baseline/test_histogram_plot_despine.png b/mapclassify/tests/baseline/test_histogram_plot_despine.png new file mode 100644 index 0000000000000000000000000000000000000000..e46eea1c0b0972fc4ab5c4bcdbe1f16537ec27f2 GIT binary patch literal 8787 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 literal 0 HcmV?d00001 diff --git a/mapclassify/tests/test_mapclassify.py b/mapclassify/tests/test_mapclassify.py index dc06e190..c042eb09 100644 --- a/mapclassify/tests/test_mapclassify.py +++ b/mapclassify/tests/test_mapclassify.py @@ -736,3 +736,23 @@ def test_pooled_bad_classifier(self): message = f"'{classifier}' not a valid classifier." with pytest.raises(ValueError, match=message): Pooled(self.data, classifier=classifier, k=4) + +class TestPlots: + def setup_method(self): + n = 20 + self.data = numpy.array([numpy.arange(n) + i * n for i in range(1, 4)]).T + + @pytest.mark.mpl_image_compare + def test_histogram_plot(self): + ax = Quantiles(self.data).plot_histogram() + return ax.get_figure() + + @pytest.mark.mpl_image_compare + def test_histogram_plot_despine(self): + ax = Quantiles(self.data).plot_histogram(despine=False) + return ax.get_figure() + + @pytest.mark.mpl_image_compare + def test_histogram_plot_linewidth(self): + ax = Quantiles(self.data).plot_histogram(linewidth=3, linecolor='red', color='yellow') + return ax.get_figure() \ No newline at end of file From ca8579355cf2c62009652743bec49d6e39023498 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 15:12:45 -0700 Subject: [PATCH 10/13] pytestmpl --- .github/workflows/testing.yml | 3 ++- ci/310-numba.yaml | 1 + ci/310.yaml | 1 + ci/311-numba.yaml | 1 + ci/311.yaml | 1 + ci/312-dev.yaml | 1 + ci/312-numba.yaml | 1 + ci/312.yaml | 1 + pyproject.toml | 26 +++++++++----------------- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index a6b3ff39..56a044b3 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -76,7 +76,8 @@ jobs: -n auto \ --color yes \ --cov mapclassify --cov-report xml --cov-append \ - --doctest-only mapclassify + --doctest-only \ + --mpl mapclassify - name: codecov (${{ matrix.os }}, ${{ matrix.environment-file }}) uses: codecov/codecov-action@v4 diff --git a/ci/310-numba.yaml b/ci/310-numba.yaml index 20cd22f1..10a9e532 100644 --- a/ci/310-numba.yaml +++ b/ci/310-numba.yaml @@ -15,6 +15,7 @@ dependencies: - pytest - pytest-cov - pytest-xdist + - pytest-mpl - codecov - matplotlib # optional diff --git a/ci/310.yaml b/ci/310.yaml index d1e7f5ef..42a7cb20 100644 --- a/ci/310.yaml +++ b/ci/310.yaml @@ -15,5 +15,6 @@ dependencies: - pytest - pytest-cov - pytest-xdist + - pytest-mpl - codecov - matplotlib diff --git a/ci/311-numba.yaml b/ci/311-numba.yaml index 3c62a28e..4639be60 100644 --- a/ci/311-numba.yaml +++ b/ci/311-numba.yaml @@ -15,6 +15,7 @@ dependencies: - pytest - pytest-cov - pytest-xdist + - pytest-mpl - codecov - matplotlib # optional diff --git a/ci/311.yaml b/ci/311.yaml index c8eb4299..2f5d309b 100644 --- a/ci/311.yaml +++ b/ci/311.yaml @@ -15,6 +15,7 @@ dependencies: - pytest - pytest-cov - pytest-xdist + - pytest-mpl - codecov - matplotlib # docs diff --git a/ci/312-dev.yaml b/ci/312-dev.yaml index 273afe06..e94b49b7 100644 --- a/ci/312-dev.yaml +++ b/ci/312-dev.yaml @@ -7,6 +7,7 @@ dependencies: - pytest - pytest-cov - pytest-xdist + - pytest-mpl - codecov # optional - pyproj diff --git a/ci/312-numba.yaml b/ci/312-numba.yaml index dd107396..54934992 100644 --- a/ci/312-numba.yaml +++ b/ci/312-numba.yaml @@ -16,6 +16,7 @@ dependencies: - pytest-cov - pytest-xdist - pytest-doctestplus + - pytest-mpl - codecov - matplotlib # optional diff --git a/ci/312.yaml b/ci/312.yaml index d1cd6ad9..5f83b27c 100644 --- a/ci/312.yaml +++ b/ci/312.yaml @@ -15,6 +15,7 @@ dependencies: - pytest - pytest-cov - pytest-xdist + - pytest-mpl - codecov - matplotlib # docs diff --git a/pyproject.toml b/pyproject.toml index 2534ba5e..5aba00a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,13 +8,13 @@ build-backend = "setuptools.build_meta" name = "mapclassify" dynamic = ["version"] maintainers = [ - {name = "Serge Rey", email = "sjsrey@gmail.com"}, - {name = "Wei Kang", email = "weikang9009@gmail.com"}, + { name = "Serge Rey", email = "sjsrey@gmail.com" }, + { name = "Wei Kang", email = "weikang9009@gmail.com" }, ] -license = {text = "BSD 3-Clause"} +license = { text = "BSD 3-Clause" } description = "Classification Schemes for Choropleth Maps." keywords = ["spatial statistics", "geovisualization"] -readme = {text = """\ +readme = { text = """\ `mapclassify` implements a family of classification schemes for choropleth maps. Its focus is on the determination of the number of classes, and the assignment of observations to those classes. It is intended for use with upstream mapping @@ -26,7 +26,7 @@ For further theoretical background see "`Choropleth Mapping`_" in Rey, S.J., D. .. _geopandas: https://geopandas.org/mapping.html .. _geoplot: https://residentmario.github.io/geoplot/user_guide/Customizing_Plots.html .. _Choropleth Mapping: https://geographicdata.science/book/notebooks/05_choropleth.html -""", content-type = "text/x-rst"} +""", content-type = "text/x-rst" } classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", @@ -52,14 +52,8 @@ Home = "https://pysal.org/mapclassify/" Repository = "https://github.com/pysal/mapclassify" [project.optional-dependencies] -speedups = [ - "numba>=0.54", -] -dev = [ - "black", - "ruff", - "pre-commit", -] +speedups = ["numba>=0.54"] +dev = ["black", "ruff", "pre-commit"] docs = [ "nbsphinx", "numpydoc", @@ -76,14 +70,12 @@ tests = [ "pytest-cov", "pytest-xdist", "pytest-doctestplus", + "pytest-mpl" ] all = ["numba[speedups,dev,docs,tests]"] [tool.setuptools.packages.find] -include = [ - "mapclassify", - "mapclassify.*", -] +include = ["mapclassify", "mapclassify.*"] [tool.black] line-length = 88 From edadacfdb59244b640284f06c21a4252d2990931 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:16:56 +0000 Subject: [PATCH 11/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mapclassify/classifiers.py | 5 +++-- mapclassify/tests/test_mapclassify.py | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index e517b0bb..b0114fda 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1164,6 +1164,7 @@ def plot_histogram( """ try: import matplotlib.pyplot as plt + if ax is None: _, ax = plt.subplots() except ImportError as e: @@ -1184,8 +1185,8 @@ def plot_histogram( ax.vlines(i, 0, lim, color=linecolor, linewidth=linewidth) # despine if specified if despine: - ax.spines['right'].set_visible(False) - ax.spines['top'].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["top"].set_visible(False) return ax diff --git a/mapclassify/tests/test_mapclassify.py b/mapclassify/tests/test_mapclassify.py index c042eb09..d90ea226 100644 --- a/mapclassify/tests/test_mapclassify.py +++ b/mapclassify/tests/test_mapclassify.py @@ -737,11 +737,12 @@ def test_pooled_bad_classifier(self): with pytest.raises(ValueError, match=message): Pooled(self.data, classifier=classifier, k=4) + class TestPlots: def setup_method(self): n = 20 self.data = numpy.array([numpy.arange(n) + i * n for i in range(1, 4)]).T - + @pytest.mark.mpl_image_compare def test_histogram_plot(self): ax = Quantiles(self.data).plot_histogram() @@ -754,5 +755,7 @@ def test_histogram_plot_despine(self): @pytest.mark.mpl_image_compare def test_histogram_plot_linewidth(self): - ax = Quantiles(self.data).plot_histogram(linewidth=3, linecolor='red', color='yellow') - return ax.get_figure() \ No newline at end of file + ax = Quantiles(self.data).plot_histogram( + linewidth=3, linecolor="red", color="yellow" + ) + return ax.get_figure() From 6897fa34c855d1a56784d8c5896d9148cea851c8 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 15:30:16 -0700 Subject: [PATCH 12/13] rm unused kwarg logic --- mapclassify/classifiers.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index b0114fda..853fdb3a 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1137,8 +1137,7 @@ def plot_histogram( Parameters ---------- color : str, optional - hue to color bars of the histogram, by default "dodgerblue". This option - overrides the 'color' entry in `hist_kwargs` if specified. + hue to color bars of the histogram, by default "dodgerblue". linecolor : str, optional color of the lines demarcating each class bin, by default "black" linewidth : int, optional @@ -1171,11 +1170,6 @@ def plot_histogram( raise ImportError from e( "You must have matplotlib available to use this function" ) - if kwargs is None: - kwargs = dict() - # override color in case specified explicitly and inside the dict - if "color" not in kwargs: - kwargs["color"] = color # plot `y` as a histogram ax.hist(self.y, **kwargs) # get the top of the ax so we know how high to raise each class bar From 61c7c25ff52697fac9bde25519c9ba313626aa72 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Wed, 26 Jun 2024 15:31:27 -0700 Subject: [PATCH 13/13] forgot color --- mapclassify/classifiers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mapclassify/classifiers.py b/mapclassify/classifiers.py index 853fdb3a..8ceae3ac 100644 --- a/mapclassify/classifiers.py +++ b/mapclassify/classifiers.py @@ -1171,7 +1171,7 @@ def plot_histogram( "You must have matplotlib available to use this function" ) # plot `y` as a histogram - ax.hist(self.y, **kwargs) + ax.hist(self.y, color=color, **kwargs) # get the top of the ax so we know how high to raise each class bar lim = ax.get_ylim()[1] # plot upper limit of each bin