diff --git a/ultraplot/axes/plot.py b/ultraplot/axes/plot.py index 39e55a896..e9078a1a4 100644 --- a/ultraplot/axes/plot.py +++ b/ultraplot/axes/plot.py @@ -6057,7 +6057,9 @@ def _apply_bar( kw = self._parse_cycle(n, **kw) # Adjust x or y coordinates for grouped and stacked bars w = _not_none(w, np.array([0.8])) # same as mpl but in *relative* units - b = _not_none(b, np.array([0.0])) # same as mpl + b = np.atleast_1d( + _not_none(b, np.array([0.0])) + ) # tolerate scalar `bottom`/`left` if not absolute_width: w = self._convert_bar_width(x, w) if stack: diff --git a/ultraplot/tests/test_1dplots.py b/ultraplot/tests/test_1dplots.py index d63256a52..d57309161 100644 --- a/ultraplot/tests/test_1dplots.py +++ b/ultraplot/tests/test_1dplots.py @@ -138,6 +138,24 @@ def test_bar_width(rng): return fig +def test_bar_scalar_bottom(): + """ + Regression for #731: pandas dispatches Series.plot(kind="barh") via + matplotlib with a scalar ``bottom`` (or ``left``), which previously hit + ``AttributeError: 'int' object has no attribute 'size'`` inside + ``_inbounds_xylim``. + """ + # Direct scalar `bottom` / `left` + fig, ax = uplt.subplots() + ax.bar([1, 2, 3], [4, 5, 6], bottom=0) + ax.barh([1, 2, 3], [4, 5, 6], left=0) + + # The original failing reproducer from the issue + series = pd.Series({"a": 1, "b": 2, "c": 3}) + fig, ax = uplt.subplots() + series.plot(kind="barh", ax=ax[0]) + + @pytest.mark.mpl_image_compare def test_bar_vectors(): """