From 70b9e96fb8b896ed959f4c70b7db09c61648411d Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Sat, 15 Aug 2020 21:53:27 +0300 Subject: [PATCH 01/10] add tests for 1702 --- seaborn/tests/test_categorical.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/seaborn/tests/test_categorical.py b/seaborn/tests/test_categorical.py index a67fc05752..fea8838b8c 100644 --- a/seaborn/tests/test_categorical.py +++ b/seaborn/tests/test_categorical.py @@ -14,7 +14,7 @@ from .. import palettes -class CategoricalFixture(object): +class CategoricalFixture: """Test boxplot (also base class for things like violinplots).""" rs = np.random.RandomState(30) n_total = 60 @@ -2606,6 +2606,24 @@ def test_factorplot(self): want_lines = self.g.unique().size + 1 nt.assert_equal(len(g.ax.lines), want_lines) + def test_share_xy(self): + + g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=True) + for ax in g.axes.flat: + assert len(ax.collections) == len(self.df.g.unique()) + + g = cat.catplot(x="y", y="g", col="g", data=self.df, sharey=True) + for ax in g.axes.flat: + assert len(ax.collections) == len(self.df.g.unique()) + + g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=False) + for ax in g.axes.flat: + assert len(ax.collections) == 1 + + g = cat.catplot(x="y", y="g", col="g", data=self.df, sharey=False) + for ax in g.axes.flat: + assert len(ax.collections) == 1 + class TestBoxenPlotter(CategoricalFixture): From 35e40ecbbb900f68daf06890c718337d06ea7040 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Sat, 15 Aug 2020 22:27:56 +0300 Subject: [PATCH 02/10] unify categories across facets only when required --- seaborn/categorical.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/seaborn/categorical.py b/seaborn/categorical.py index 34aa383da8..9f98ffa8b4 100644 --- a/seaborn/categorical.py +++ b/seaborn/categorical.py @@ -3802,9 +3802,11 @@ def catplot( # Determine keyword arguments for the plotting function plot_kws = dict( - order=order, hue_order=hue_order, - orient=orient, color=color, palette=palette, + hue_order=hue_order, orient=orient, color=color, palette=palette, ) + # Synchronize categories across facets, when required + if (sharex and p.orient == "v") or (sharey and p.orient == "h"): + plot_kws["order"] = order plot_kws.update(kwargs) if kind in ["bar", "point"]: @@ -3889,7 +3891,8 @@ def catplot( Categorical variables that will determine the faceting of the grid. {col_wrap} {stat_api_params} - {order_vars} + {order_vars} ``order`` is ignored if the ``share`` parameter for the + categorical axis is ``False``. row_order, col_order : lists of strings, optional Order to organize the rows and/or columns of the grid in, otherwise the orders are inferred from the data objects. From 0a1ad5f2772f211ca16686e83ab8eeef9938df98 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Sun, 16 Aug 2020 13:05:17 +0300 Subject: [PATCH 03/10] document count as allowed kind parameter --- seaborn/categorical.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/seaborn/categorical.py b/seaborn/categorical.py index 9f98ffa8b4..5a33740da6 100644 --- a/seaborn/categorical.py +++ b/seaborn/categorical.py @@ -3896,10 +3896,10 @@ def catplot( row_order, col_order : lists of strings, optional Order to organize the rows and/or columns of the grid in, otherwise the orders are inferred from the data objects. - kind : string, optional - The kind of plot to draw (corresponds to the name of a categorical - plotting function. Options are: "point", "bar", "strip", "swarm", - "box", "violin", or "boxen". + kind : str, optional + The kind of plot to draw, corresponds to the name of a categorical + axes-level plotting function. Options are: "strip", "swarm", "box", "violin", + "boxen", "point", "bar", or "count". {height} {aspect} {orient} From d344fbe38395d7d0b119d926faedcbc9a66e0acc Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:59:20 +0300 Subject: [PATCH 04/10] Honor user order input --- seaborn/categorical.py | 17 ++++++++++------- seaborn/tests/test_categorical.py | 10 ++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/seaborn/categorical.py b/seaborn/categorical.py index 5a33740da6..f00814fcf9 100644 --- a/seaborn/categorical.py +++ b/seaborn/categorical.py @@ -3778,7 +3778,13 @@ def catplot( p = _CategoricalPlotter() p.require_numeric = plotter_class.require_numeric p.establish_variables(x_, y_, hue, data, orient, order, hue_order) - order = p.group_names + if ( + order is not None + or (sharex and p.orient == "v") + or (sharey and p.orient == "h") + ): + # Sync categorical axis between facets to have the same categories + order = p.group_names hue_order = p.hue_names # Determine the palette to use @@ -3802,11 +3808,9 @@ def catplot( # Determine keyword arguments for the plotting function plot_kws = dict( - hue_order=hue_order, orient=orient, color=color, palette=palette, + order=order, hue_order=hue_order, + orient=orient, color=color, palette=palette, ) - # Synchronize categories across facets, when required - if (sharex and p.orient == "v") or (sharey and p.orient == "h"): - plot_kws["order"] = order plot_kws.update(kwargs) if kind in ["bar", "point"]: @@ -3891,8 +3895,7 @@ def catplot( Categorical variables that will determine the faceting of the grid. {col_wrap} {stat_api_params} - {order_vars} ``order`` is ignored if the ``share`` parameter for the - categorical axis is ``False``. + {order_vars} row_order, col_order : lists of strings, optional Order to organize the rows and/or columns of the grid in, otherwise the orders are inferred from the data objects. diff --git a/seaborn/tests/test_categorical.py b/seaborn/tests/test_categorical.py index fea8838b8c..9ec58e51ff 100644 --- a/seaborn/tests/test_categorical.py +++ b/seaborn/tests/test_categorical.py @@ -2624,6 +2624,16 @@ def test_share_xy(self): for ax in g.axes.flat: assert len(ax.collections) == 1 + # Make sure order is used if given regardless of sharex value + order = self.df.g.unique() + g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=False, order=order) + for ax in g.axes.flat: + assert len(ax.collections) == len(self.df.g.unique()) + + g = cat.catplot(x="y", y="g", col="g", data=self.df, sharey=False, order=order) + for ax in g.axes.flat: + assert len(ax.collections) == len(self.df.g.unique()) + class TestBoxenPlotter(CategoricalFixture): From 6c09c8e7af60f0532c805907c95d929374017043 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Tue, 18 Aug 2020 21:02:23 +0300 Subject: [PATCH 05/10] remove lvplot remnants --- seaborn/categorical.py | 1 - 1 file changed, 1 deletion(-) diff --git a/seaborn/categorical.py b/seaborn/categorical.py index f00814fcf9..6b22c0b210 100644 --- a/seaborn/categorical.py +++ b/seaborn/categorical.py @@ -3768,7 +3768,6 @@ def catplot( "box": _BoxPlotter, "violin": _ViolinPlotter, "boxen": _LVPlotter, - "lv": _LVPlotter, "bar": _BarPlotter, "point": _PointPlotter, "strip": _StripPlotter, From 0af981cbb467358d8b4943a7fffba22050f53454 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Wed, 19 Aug 2020 21:58:30 +0300 Subject: [PATCH 06/10] warn if different categories may share color --- seaborn/categorical.py | 10 ++++++++++ seaborn/tests/test_categorical.py | 33 +++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/seaborn/categorical.py b/seaborn/categorical.py index 6b22c0b210..aa26b6a9c3 100644 --- a/seaborn/categorical.py +++ b/seaborn/categorical.py @@ -3784,6 +3784,16 @@ def catplot( ): # Sync categorical axis between facets to have the same categories order = p.group_names + elif color is None: + msg = ( + "Setting `{}=False` with `color=None` may cause different levels of the " + "`{}` variable to share colors. This will change in a future version." + ) + if not sharex and p.orient == "v": + warnings.warn(msg.format("sharex", "x"), UserWarning) + if not sharey and p.orient == "h": + warnings.warn(msg.format("sharey", "y"), UserWarning) + hue_order = p.hue_names # Determine the palette to use diff --git a/seaborn/tests/test_categorical.py b/seaborn/tests/test_categorical.py index 9ec58e51ff..e2cb50ff06 100644 --- a/seaborn/tests/test_categorical.py +++ b/seaborn/tests/test_categorical.py @@ -2608,6 +2608,7 @@ def test_factorplot(self): def test_share_xy(self): + # Test default behavior works g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=True) for ax in g.axes.flat: assert len(ax.collections) == len(self.df.g.unique()) @@ -2616,15 +2617,31 @@ def test_share_xy(self): for ax in g.axes.flat: assert len(ax.collections) == len(self.df.g.unique()) - g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=False) - for ax in g.axes.flat: - assert len(ax.collections) == 1 - - g = cat.catplot(x="y", y="g", col="g", data=self.df, sharey=False) - for ax in g.axes.flat: - assert len(ax.collections) == 1 + # Test unsharing works + with pytest.warns(UserWarning): + g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=False) + for ax in g.axes.flat: + assert len(ax.collections) == 1 - # Make sure order is used if given regardless of sharex value + with pytest.warns(UserWarning): + g = cat.catplot(x="y", y="g", col="g", data=self.df, sharey=False) + for ax in g.axes.flat: + assert len(ax.collections) == 1 + + # Make sure no warning is raised if color is provided on unshared plot + with pytest.warns(None) as record: + g = cat.catplot( + x="g", y="y", col="g", data=self.df, sharex=False, color="b" + ) + assert not len(record) + + with pytest.warns(None) as record: + g = cat.catplot( + x="y", y="g", col="g", data=self.df, sharey=False, color="r" + ) + assert not len(record) + + # Make sure order is used if given, regardless of sharex value order = self.df.g.unique() g = cat.catplot(x="g", y="y", col="g", data=self.df, sharex=False, order=order) for ax in g.axes.flat: From 5fc742952d7d838081bc5e847628762905c735c2 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Wed, 19 Aug 2020 23:24:25 +0300 Subject: [PATCH 07/10] update release notes --- doc/releases/v0.11.0.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/releases/v0.11.0.txt b/doc/releases/v0.11.0.txt index 3e5449d837..5a0fb8a065 100644 --- a/doc/releases/v0.11.0.txt +++ b/doc/releases/v0.11.0.txt @@ -70,6 +70,8 @@ Other - Improved the error messages produced when categorical plots process the orientation parameter. +- Allowed :func:`catplot` to not unify categories across facets if the categorical axis is not shared (i.e. by specifying ``sharex=False``) (:pr:`2196`). + - Deprecated the ``axlabel`` function; use ``ax.set(xlabel=, ylabel=)`` instead. - Deprecated the ``iqr`` function; use :func:`scipy.stats.iqr` instead. From 4b8d782aa47819caf53516fa041b852187d9baa5 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Thu, 20 Aug 2020 10:29:48 +0300 Subject: [PATCH 08/10] don't warn if hue is provided --- seaborn/categorical.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seaborn/categorical.py b/seaborn/categorical.py index 56046f4656..9cb713811a 100644 --- a/seaborn/categorical.py +++ b/seaborn/categorical.py @@ -3784,7 +3784,7 @@ def catplot( ): # Sync categorical axis between facets to have the same categories order = p.group_names - elif color is None: + elif color is None and hue is None: msg = ( "Setting `{}=False` with `color=None` may cause different levels of the " "`{}` variable to share colors. This will change in a future version." From 871c1b84395f69b50e3913305b8897f3fffa5e56 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Thu, 20 Aug 2020 11:05:28 +0300 Subject: [PATCH 09/10] fix failing jointplot example --- seaborn/axisgrid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/seaborn/axisgrid.py b/seaborn/axisgrid.py index 41376e4e65..a75cb3f093 100644 --- a/seaborn/axisgrid.py +++ b/seaborn/axisgrid.py @@ -2369,8 +2369,7 @@ def jointplot( :context: close-figs >>> g = sns.jointplot(x="petal_length", y="sepal_length", data=iris, - ... marginal_kws=dict(bins=15, rug=True), - ... marker="+") + ... marginal_kws=dict(bins=15), marker="+") """ # Avoid circular import From 2aee18899f0c35c1a9a70dd2c25546209042e685 Mon Sep 17 00:00:00 2001 From: Maoz Gelbart <13831112+MaozGelbart@users.noreply.github.com> Date: Thu, 20 Aug 2020 12:49:25 +0300 Subject: [PATCH 10/10] fix distplot example 6 --- seaborn/distributions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seaborn/distributions.py b/seaborn/distributions.py index 380d3ef86f..9f11ac695a 100644 --- a/seaborn/distributions.py +++ b/seaborn/distributions.py @@ -2510,8 +2510,8 @@ def distplot(a=None, bins=None, hist=True, kde=True, rug=False, fit=None, Change the color of all the plot elements: .. plot:: - :context: close-figs + >>> sns.set_color_codes() >>> ax = sns.distplot(x, color="y")