Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 33b3015

Browse files
Improve bar_label annotation (#22447)
Co-authored-by: Tim Hoffmann <[email protected]>
1 parent c9614de commit 33b3015

File tree

2 files changed

+93
-6
lines changed

2 files changed

+93
-6
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,13 +2597,25 @@ def bar_label(self, container, labels=None, *, fmt="%g", label_type="edge",
25972597
25982598
**kwargs
25992599
Any remaining keyword arguments are passed through to
2600-
`.Axes.annotate`.
2600+
`.Axes.annotate`. The alignment parameters (
2601+
*horizontalalignment* / *ha*, *verticalalignment* / *va*) are
2602+
not supported because the labels are automatically aligned to
2603+
the bars.
26012604
26022605
Returns
26032606
-------
26042607
list of `.Text`
26052608
A list of `.Text` instances for the labels.
26062609
"""
2610+
for key in ['horizontalalignment', 'ha', 'verticalalignment', 'va']:
2611+
if key in kwargs:
2612+
raise ValueError(
2613+
f"Passing {key!r} to bar_label() is not supported.")
2614+
2615+
a, b = self.yaxis.get_view_interval()
2616+
y_inverted = a > b
2617+
c, d = self.xaxis.get_view_interval()
2618+
x_inverted = c > d
26072619

26082620
# want to know whether to put label on positive or negative direction
26092621
# cannot use np.sign here because it will return 0 if x == 0
@@ -2632,7 +2644,7 @@ def sign(x):
26322644
annotations = []
26332645

26342646
for bar, err, dat, lbl in itertools.zip_longest(
2635-
bars, errs, datavalues, labels
2647+
bars, errs, datavalues, labels
26362648
):
26372649
(x0, y0), (x1, y1) = bar.get_bbox().get_points()
26382650
xc, yc = (x0 + x1) / 2, (y0 + y1) / 2
@@ -2664,18 +2676,26 @@ def sign(x):
26642676
xy = endpt, yc
26652677

26662678
if orientation == "vertical":
2667-
xytext = 0, sign(dat) * padding
2679+
y_direction = -1 if y_inverted else 1
2680+
xytext = 0, y_direction * sign(dat) * padding
26682681
else:
2669-
xytext = sign(dat) * padding, 0
2682+
x_direction = -1 if x_inverted else 1
2683+
xytext = x_direction * sign(dat) * padding, 0
26702684

26712685
if label_type == "center":
26722686
ha, va = "center", "center"
26732687
elif label_type == "edge":
26742688
if orientation == "vertical":
26752689
ha = 'center'
2676-
va = 'top' if dat < 0 else 'bottom' # also handles NaN
2690+
if y_inverted:
2691+
va = 'top' if dat > 0 else 'bottom' # also handles NaN
2692+
else:
2693+
va = 'top' if dat < 0 else 'bottom' # also handles NaN
26772694
elif orientation == "horizontal":
2678-
ha = 'right' if dat < 0 else 'left' # also handles NaN
2695+
if x_inverted:
2696+
ha = 'right' if dat > 0 else 'left' # also handles NaN
2697+
else:
2698+
ha = 'right' if dat < 0 else 'left' # also handles NaN
26792699
va = 'center'
26802700

26812701
if np.isnan(dat):

lib/matplotlib/tests/test_axes.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7386,6 +7386,20 @@ def test_bar_label_location_vertical():
73867386
assert labels[1].get_va() == 'top'
73877387

73887388

7389+
def test_bar_label_location_vertical_yinverted():
7390+
ax = plt.gca()
7391+
ax.invert_yaxis()
7392+
xs, heights = [1, 2], [3, -4]
7393+
rects = ax.bar(xs, heights)
7394+
labels = ax.bar_label(rects)
7395+
assert labels[0].xy == (xs[0], heights[0])
7396+
assert labels[0].get_ha() == 'center'
7397+
assert labels[0].get_va() == 'top'
7398+
assert labels[1].xy == (xs[1], heights[1])
7399+
assert labels[1].get_ha() == 'center'
7400+
assert labels[1].get_va() == 'bottom'
7401+
7402+
73897403
def test_bar_label_location_horizontal():
73907404
ax = plt.gca()
73917405
ys, widths = [1, 2], [3, -4]
@@ -7399,6 +7413,49 @@ def test_bar_label_location_horizontal():
73997413
assert labels[1].get_va() == 'center'
74007414

74017415

7416+
def test_bar_label_location_horizontal_yinverted():
7417+
ax = plt.gca()
7418+
ax.invert_yaxis()
7419+
ys, widths = [1, 2], [3, -4]
7420+
rects = ax.barh(ys, widths)
7421+
labels = ax.bar_label(rects)
7422+
assert labels[0].xy == (widths[0], ys[0])
7423+
assert labels[0].get_ha() == 'left'
7424+
assert labels[0].get_va() == 'center'
7425+
assert labels[1].xy == (widths[1], ys[1])
7426+
assert labels[1].get_ha() == 'right'
7427+
assert labels[1].get_va() == 'center'
7428+
7429+
7430+
def test_bar_label_location_horizontal_xinverted():
7431+
ax = plt.gca()
7432+
ax.invert_xaxis()
7433+
ys, widths = [1, 2], [3, -4]
7434+
rects = ax.barh(ys, widths)
7435+
labels = ax.bar_label(rects)
7436+
assert labels[0].xy == (widths[0], ys[0])
7437+
assert labels[0].get_ha() == 'right'
7438+
assert labels[0].get_va() == 'center'
7439+
assert labels[1].xy == (widths[1], ys[1])
7440+
assert labels[1].get_ha() == 'left'
7441+
assert labels[1].get_va() == 'center'
7442+
7443+
7444+
def test_bar_label_location_horizontal_xyinverted():
7445+
ax = plt.gca()
7446+
ax.invert_xaxis()
7447+
ax.invert_yaxis()
7448+
ys, widths = [1, 2], [3, -4]
7449+
rects = ax.barh(ys, widths)
7450+
labels = ax.bar_label(rects)
7451+
assert labels[0].xy == (widths[0], ys[0])
7452+
assert labels[0].get_ha() == 'right'
7453+
assert labels[0].get_va() == 'center'
7454+
assert labels[1].xy == (widths[1], ys[1])
7455+
assert labels[1].get_ha() == 'left'
7456+
assert labels[1].get_va() == 'center'
7457+
7458+
74027459
def test_bar_label_location_center():
74037460
ax = plt.gca()
74047461
ys, widths = [1, 2], [3, -4]
@@ -7450,6 +7507,16 @@ def test_bar_label_nan_ydata():
74507507
assert labels[0].get_va() == 'bottom'
74517508

74527509

7510+
def test_bar_label_nan_ydata_inverted():
7511+
ax = plt.gca()
7512+
ax.yaxis_inverted()
7513+
bars = ax.bar([2, 3], [np.nan, 1])
7514+
labels = ax.bar_label(bars)
7515+
assert [l.get_text() for l in labels] == ['', '1']
7516+
assert labels[0].xy == (2, 0)
7517+
assert labels[0].get_va() == 'bottom'
7518+
7519+
74537520
def test_patch_bounds(): # PR 19078
74547521
fig, ax = plt.subplots()
74557522
ax.add_patch(mpatches.Wedge((0, -1), 1.05, 60, 120, 0.1))

0 commit comments

Comments
 (0)