Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f730235

Browse files
brifore13timhoffm
andauthored
ENH: Add support for per-label padding in bar_label (matplotlib#29696)
Implement support for array-like padding in bar_label. This allows users to specify different padding values for individual labels by passing an array-like object to the padding parameter. --------- Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
1 parent f1e7d3b commit f730235

File tree

5 files changed

+41
-7
lines changed

5 files changed

+41
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``bar_label`` supports individual padding per label
2+
---------------------------------------------------
3+
``bar_label`` will now accept both a float value or an array-like for
4+
padding. The array-like defines the padding for each label individually.

‎lib/matplotlib/axes/_axes.py‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2803,8 +2803,11 @@ def bar_label(self, container, labels=None, *, fmt="%g", label_type="edge",
28032803
(useful for stacked bars, i.e.,
28042804
:doc:`/gallery/lines_bars_and_markers/bar_label_demo`)
28052805
2806-
padding : float, default: 0
2806+
padding : float or array-like, default: 0
28072807
Distance of label from the end of the bar, in points.
2808+
If an array-like is provided, the padding values are applied
2809+
to each label individually. Must have the same length as container.
2810+
.. versionadded:: 3.11
28082811
28092812
**kwargs
28102813
Any remaining keyword arguments are passed through to
@@ -2854,8 +2857,18 @@ def sign(x):
28542857

28552858
annotations = []
28562859

2857-
for bar, err, dat, lbl in itertools.zip_longest(
2858-
bars, errs, datavalues, labels
2860+
if np.iterable(padding):
2861+
# if padding iterable, check length
2862+
padding = np.asarray(padding)
2863+
if len(padding) != len(bars):
2864+
raise ValueError(
2865+
f"padding must be of length {len(bars)} when passed as a sequence")
2866+
else:
2867+
# single value, apply to all labels
2868+
padding = [padding] * len(bars)
2869+
2870+
for bar, err, dat, lbl, pad in itertools.zip_longest(
2871+
bars, errs, datavalues, labels, padding
28592872
):
28602873
(x0, y0), (x1, y1) = bar.get_bbox().get_points()
28612874
xc, yc = (x0 + x1) / 2, (y0 + y1) / 2
@@ -2895,10 +2908,10 @@ def sign(x):
28952908

28962909
if orientation == "vertical":
28972910
y_direction = -1 if y_inverted else 1
2898-
xytext = 0, y_direction * sign(dat) * padding
2911+
xytext = 0, y_direction * sign(dat) * pad
28992912
else: # horizontal
29002913
x_direction = -1 if x_inverted else 1
2901-
xytext = x_direction * sign(dat) * padding, 0
2914+
xytext = x_direction * sign(dat) * pad, 0
29022915

29032916
if label_type == "center":
29042917
ha, va = "center", "center"

‎lib/matplotlib/axes/_axes.pyi‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class Axes(_AxesBase):
256256
*,
257257
fmt: str | Callable[[float], str] = ...,
258258
label_type: Literal["center", "edge"] = ...,
259-
padding: float = ...,
259+
padding: float |ArrayLike= ...,
260260
**kwargs
261261
) -> list[Annotation]: ...
262262
def broken_barh(

‎lib/matplotlib/pyplot.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3027,7 +3027,7 @@ def bar_label(
30273027
*,
30283028
fmt: str | Callable[[float], str] = "%g",
30293029
label_type: Literal["center", "edge"] = "edge",
3030-
padding: float = 0,
3030+
padding: float |ArrayLike= 0,
30313031
**kwargs,
30323032
) -> list[Annotation]:
30333033
return gca().bar_label(

‎lib/matplotlib/tests/test_axes.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8816,6 +8816,23 @@ def test_bar_label_nan_ydata_inverted():
88168816
assert labels[0].get_verticalalignment() == 'bottom'
88178817

88188818

8819+
def test_bar_label_padding():
8820+
"""Test that bar_label accepts both float and array-like padding."""
8821+
ax = plt.gca()
8822+
xs, heights = [1, 2], [3, 4]
8823+
rects = ax.bar(xs, heights)
8824+
labels1 = ax.bar_label(rects, padding=5) # test float value
8825+
assert labels1[0].xyann[1] == 5
8826+
assert labels1[1].xyann[1] == 5
8827+
8828+
labels2 = ax.bar_label(rects, padding=[2, 8]) # test array-like values
8829+
assert labels2[0].xyann[1] == 2
8830+
assert labels2[1].xyann[1] == 8
8831+
8832+
with pytest.raises(ValueError, match="padding must be of length"):
8833+
ax.bar_label(rects, padding=[1, 2, 3])
8834+
8835+
88198836
def test_nan_barlabels():
88208837
fig, ax = plt.subplots()
88218838
bars = ax.bar([1, 2, 3], [np.nan, 1, 2], yerr=[0.2, 0.4, 0.6])

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /