Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve robustness to empty data in Plot and Nominal #3202

Merged
merged 2 commits into from
Dec 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/whatsnew/v0.12.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ v0.12.2 (Unreleased)

- |Fix| Fixed a bug where legends for numeric variables with large values with be incorrectly shown (i.e. with a missing offset or exponent; :pr:`3187`).

- |Fix| Improve robustness to empty data in several components of the objects interface (:pr:`3202`).

- |Fix| Fixed a regression in v0.12.0 where manually-added labels could have duplicate legend entries (:pr:`3116`).

- |Fix| Fixed a bug in :func:`histplot` with `kde=True` and `log_scale=True` where the curve was not scaled properly (:pr:`3173`).
Expand Down
7 changes: 3 additions & 4 deletions seaborn/_core/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1466,8 +1466,6 @@ def _setup_split_generator(
self, grouping_vars: list[str], df: DataFrame, subplots: list[dict[str, Any]],
) -> Callable[[], Generator]:

allow_empty = False # TODO will need to recreate previous categorical plots

grouping_keys = []
grouping_vars = [
v for v in grouping_vars if v in df and v not in ["col", "row"]
Expand Down Expand Up @@ -1506,7 +1504,8 @@ def split_generator(keep_na=False) -> Generator:
subplot_keys[dim] = view[dim]

if not grouping_vars or not any(grouping_keys):
yield subplot_keys, axes_df.copy(), view["ax"]
if not axes_df.empty:
yield subplot_keys, axes_df.copy(), view["ax"]
continue

grouped_df = axes_df.groupby(grouping_vars, sort=False, as_index=False)
Expand All @@ -1526,7 +1525,7 @@ def split_generator(keep_na=False) -> Generator:
# case this option could be removed
df_subset = axes_df.loc[[]]

if df_subset.empty and not allow_empty:
if df_subset.empty:
continue

sub_vars = dict(zip(grouping_vars, key))
Expand Down
2 changes: 1 addition & 1 deletion seaborn/_core/scales.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def _setup(
new = new.label()

# TODO flexibility over format() which isn't great for numbers / dates
stringify = np.vectorize(format)
stringify = np.vectorize(format, otypes=["object"])

units_seed = categorical_order(data, new.order)

Expand Down
9 changes: 5 additions & 4 deletions tests/_core/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,8 +680,9 @@ def test_matplotlib_object_creation(self):
def test_empty(self):

m = MockMark()
Plot().plot()
Plot().add(m).plot()
assert m.n_splits == 0
assert not m.passed_data

def test_no_orient_variance(self):

Expand Down Expand Up @@ -1086,7 +1087,7 @@ def test_on_axes(self):

ax = mpl.figure.Figure().subplots()
m = MockMark()
p = Plot().on(ax).add(m).plot()
p = Plot([1], [2]).on(ax).add(m).plot()
assert m.passed_axes == [ax]
assert p._figure is ax.figure

Expand All @@ -1095,7 +1096,7 @@ def test_on_figure(self, facet):

f = mpl.figure.Figure()
m = MockMark()
p = Plot().on(f).add(m)
p = Plot([1, 2], [3, 4]).on(f).add(m)
if facet:
p = p.facet(["a", "b"])
p = p.plot()
Expand All @@ -1112,7 +1113,7 @@ def test_on_subfigure(self, facet):
sf1, sf2 = mpl.figure.Figure().subfigures(2)
sf1.subplots()
m = MockMark()
p = Plot().on(sf2).add(m)
p = Plot([1, 2], [3, 4]).on(sf2).add(m)
if facet:
p = p.facet(["a", "b"])
p = p.plot()
Expand Down
6 changes: 6 additions & 0 deletions tests/_core/test_scales.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,12 @@ class MockProperty(IntervalProperty):
s = Nominal((2, 4))._setup(x, MockProperty())
assert_array_equal(s(x), [4, np.sqrt(10), 2, np.sqrt(10)])

def test_empty_data(self):

x = pd.Series([], dtype=object, name="x")
s = Nominal()._setup(x, Coordinate())
assert_array_equal(s(x), [])


class TestTemporal:

Expand Down