Skip to content

Commit fb77685

Browse files
committed
ENH: Add align parameter to broken_barh()
In particular `align="center"` makes it easier to position bars centered on labels, as illustrated in the changed example. Note: This parameter is similar to `bar(..., align=...)`.
1 parent 70d0bf7 commit fb77685

File tree

6 files changed

+52
-11
lines changed

6 files changed

+52
-11
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``broken_barh()`` vertical alignment though ``align`` parameter
2+
---------------------------------------------------------------
3+
`~.Axes.broken_barh` now supports vertical alignment of the bars through the
4+
``align`` parameter.

galleries/examples/lines_bars_and_markers/broken_barh.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
network = np.column_stack([10*np.random.random(10), np.full(10, 0.05)])
1919

2020
fig, ax = plt.subplots()
21-
# broken_barh(xranges, (ymin, height))
22-
ax.broken_barh(cpu_1, (-0.2, 0.4))
23-
ax.broken_barh(cpu_2, (0.8, 0.4))
24-
ax.broken_barh(cpu_3, (1.8, 0.4))
25-
ax.broken_barh(cpu_4, (2.8, 0.4))
26-
ax.broken_barh(disk, (3.8, 0.4), color="tab:orange")
27-
ax.broken_barh(network, (4.8, 0.4), color="tab:green")
21+
# broken_barh(xranges, (ypos, height))
22+
ax.broken_barh(cpu_1, (0, 0.4), align="center")
23+
ax.broken_barh(cpu_2, (1, 0.4), align="center")
24+
ax.broken_barh(cpu_3, (2, 0.4), align="center")
25+
ax.broken_barh(cpu_4, (3, 0.4), align="center")
26+
ax.broken_barh(disk, (4, 0.4), align="center", color="tab:orange")
27+
ax.broken_barh(network, (5, 0.4), align="center", color="tab:green")
2828
ax.set_xlim(0, 10)
2929
ax.set_yticks(range(6),
3030
labels=["CPU 1", "CPU 2", "CPU 3", "CPU 4", "disk", "network"])

lib/matplotlib/axes/_axes.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2935,7 +2935,7 @@ def sign(x):
29352935

29362936
@_preprocess_data()
29372937
@_docstring.interpd
2938-
def broken_barh(self, xranges, yrange, **kwargs):
2938+
def broken_barh(self, xranges, yrange, align="bottom", **kwargs):
29392939
"""
29402940
Plot a horizontal sequence of rectangles.
29412941
@@ -2948,8 +2948,16 @@ def broken_barh(self, xranges, yrange, **kwargs):
29482948
The x-positions and extents of the rectangles. For each tuple
29492949
(*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* +
29502950
*xwidth*.
2951-
yrange : (*ymin*, *yheight*)
2951+
yrange : (*ypos*, *yheight*)
29522952
The y-position and extent for all the rectangles.
2953+
align : {"bottom", "center", "top"}, default: 'bottom'
2954+
The alignment of the yrange with respect to the y-position. One of:
2955+
2956+
- "bottom": Resulting y-range [ypos, ypos + yheight]
2957+
- "center": Resulting y-range [ypos - yheight/2, ypos + yheight/2]
2958+
- "top": Resulting y-range [ypos - yheight, ypos]
2959+
2960+
.. versionadded:: 3.11
29532961
29542962
Returns
29552963
-------
@@ -2984,7 +2992,15 @@ def broken_barh(self, xranges, yrange, **kwargs):
29842992

29852993
vertices = []
29862994
y0, dy = yrange
2987-
y0, y1 = self.convert_yunits((y0, y0 + dy))
2995+
2996+
_api.check_in_list(['bottom', 'center', 'top'], align=align)
2997+
if align == "bottom":
2998+
y0, y1 = self.convert_yunits((y0, y0 + dy))
2999+
elif align == "center":
3000+
y0, y1 = self.convert_yunits((y0 - dy/2, y0 + dy/2))
3001+
else:
3002+
y0, y1 = self.convert_yunits((y0 - dy, y0))
3003+
29883004
for xr in xranges: # convert the absolute values, not the x and dx
29893005
try:
29903006
x0, dx = xr

lib/matplotlib/axes/_axes.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ class Axes(_AxesBase):
263263
self,
264264
xranges: Sequence[tuple[float, float]],
265265
yrange: tuple[float, float],
266+
align: Literal["bottom", "center", "top"] = ...,
266267
*,
267268
data=...,
268269
**kwargs

lib/matplotlib/pyplot.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3111,12 +3111,17 @@ def boxplot(
31113111
def broken_barh(
31123112
xranges: Sequence[tuple[float, float]],
31133113
yrange: tuple[float, float],
3114+
align: Literal["bottom", "center", "top"] = "bottom",
31143115
*,
31153116
data=None,
31163117
**kwargs,
31173118
) -> PolyCollection:
31183119
return gca().broken_barh(
3119-
xranges, yrange, **({"data": data} if data is not None else {}), **kwargs
3120+
xranges,
3121+
yrange,
3122+
align=align,
3123+
**({"data": data} if data is not None else {}),
3124+
**kwargs,
31203125
)
31213126

31223127

lib/matplotlib/tests/test_axes.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7134,6 +7134,21 @@ def test_broken_barh_timedelta():
71347134
assert pp.get_paths()[0].vertices[2, 0] == mdates.date2num(d0) + 1 / 24
71357135

71367136

7137+
def test_broken_barh_align():
7138+
fig, ax = plt.subplots()
7139+
pc = ax.broken_barh([(0, 10)], (0, 2))
7140+
for path in pc.get_paths():
7141+
assert_array_equal(path.get_extents().intervaly, [0, 2])
7142+
7143+
pc = ax.broken_barh([(0, 10)], (10, 2), align="center")
7144+
for path in pc.get_paths():
7145+
assert_array_equal(path.get_extents().intervaly, [9, 11])
7146+
7147+
pc = ax.broken_barh([(0, 10)], (20, 2), align="top")
7148+
for path in pc.get_paths():
7149+
assert_array_equal(path.get_extents().intervaly, [18, 20])
7150+
7151+
71377152
def test_pandas_pcolormesh(pd):
71387153
time = pd.date_range('2000-01-01', periods=10)
71397154
depth = np.arange(20)

0 commit comments

Comments
 (0)