diff --git a/ultraplot/axes/plot.py b/ultraplot/axes/plot.py index a4388d3d3..d5ad59cfe 100644 --- a/ultraplot/axes/plot.py +++ b/ultraplot/axes/plot.py @@ -6279,6 +6279,14 @@ def _apply_boxplot( # Use vert parameter artists = self._call_native("boxplot", y, vert=vert, **kw) + if kw.get("manage_ticks", True): + getter = self.get_xticks if vert else self.get_yticks + setter = self.set_xticks if vert else self.set_yticks + ticks = getter() + unique_ticks = list(dict.fromkeys(ticks)) + if len(unique_ticks) != len(ticks): + setter(unique_ticks) + artists = artists or {} # necessary? artists = { key: cbook.silent_list(type(objs[0]).__name__, objs) if objs else objs diff --git a/ultraplot/tests/test_statistical_plotting.py b/ultraplot/tests/test_statistical_plotting.py index 2c82b14ff..88ec7c062 100644 --- a/ultraplot/tests/test_statistical_plotting.py +++ b/ultraplot/tests/test_statistical_plotting.py @@ -482,3 +482,19 @@ def test_ridgeline_continuous_auto_height(rng): artists = ax.ridgeline([data[0]], positions=[0]) assert len(artists) == 1 uplt.close(fig) + + +def test_boxplot_shared_x_does_not_duplicate_ticks(rng): + data = [rng.random(size=j * 50) for j in range(1, 11)] + fig, axs = uplt.subplots(nrows=2, ncols=2, sharex=2, sharey=False) + + for ax in axs: + ax.boxplot(data, showfliers=False, lw=0.5) + + fig.canvas.draw() + + for ax in axs: + ticks = [int(t) for t in ax.get_xticks()] + assert ticks == list(range(10)) + + uplt.close(fig)