Skip to content

Commit 14a8097

Browse files
committed
Add colors and kwargs, typing stubs, pyplot wrapper
1 parent d7f7238 commit 14a8097

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed

galleries/examples/lines_bars_and_markers/grouped_bar_chart.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,25 @@
145145
axs[1, 1].grouped_bar(x, data, group_spacing=0.5, bar_spacing=0.1)
146146

147147

148+
# %%
149+
# Styling
150+
# -------
151+
# The bars can be styled through additional keyword arguments. Currently,
152+
# the only per-dataset setting is ``colors``. Additionally, all
153+
# `.Rectangle parameters` are passed through and applied to all datasets.
154+
155+
x = ['A', 'B', 'C']
156+
data = {
157+
'data1': [1, 2, 3],
158+
'data2': [1.2, 2.2, 3.2],
159+
'data3': [1.4, 2.4, 3.4],
160+
'data4': [1.6, 2.6, 3.6],
161+
}
162+
163+
fig, ax = plt.subplots()
164+
ax.grouped_bar(x, data, colors=["r", "g", "b", "m"], edgecolor="black")
165+
166+
148167
# %%
149168
# Horizontal grouped bars
150169
# -----------------------

lib/matplotlib/axes/_axes.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,10 +3049,17 @@ def broken_barh(self, xranges, yrange, **kwargs):
30493049
return col
30503050

30513051
def grouped_bar(self, x, heights, *, group_spacing=1.5, bar_spacing=0,
3052-
dataset_labels=None, orientation="vertical"):
3052+
dataset_labels=None, orientation="vertical", colors=None,
3053+
**kwargs):
30533054
"""
3055+
Make a grouped bar plot.
3056+
3057+
.. note::
3058+
This function is new in v3.10, and the API is still provisional.
3059+
We may still fine-tune some aspects based on user-feedback.
3060+
30543061
Parameters
3055-
-----------
3062+
----------
30563063
x : array-like or list of str
30573064
The center positions of the bar groups. If these are numeric values,
30583065
they have to be equidistant. As with `~.Axes.bar`, you can provide
@@ -3116,9 +3123,20 @@ def grouped_bar(self, x, heights, *, group_spacing=1.5, bar_spacing=0,
31163123
The labels of the datasets.
31173124
31183125
orientation : {"vertical", "horizontal"}, default: vertical
3119-
"""
3120-
_api.check_in_list(["vertical", "horizontal"], orientation=orientation)
31213126
3127+
colors : list of :mpltype:`color`, optional
3128+
A sequence of colors to be cycled through and used to color bars
3129+
of the different datasets. The sequence need not be exactly the
3130+
same length as the number of provided y, in which case the colors
3131+
will repeat from the beginning.
3132+
3133+
If not specified, the colors from the Axes property cycle will be used.
3134+
3135+
**kwargs : `.Rectangle` properties
3136+
3137+
%(Rectangle:kwdoc)s
3138+
3139+
"""
31223140
if hasattr(heights, 'keys'):
31233141
if dataset_labels is not None:
31243142
raise ValueError(
@@ -3153,6 +3171,15 @@ def grouped_bar(self, x, heights, *, group_spacing=1.5, bar_spacing=0,
31533171
f"has {len(dataset)} groups"
31543172
)
31553173

3174+
_api.check_in_list(["vertical", "horizontal"], orientation=orientation)
3175+
3176+
if colors is None:
3177+
colors = itertools.cycle([None])
3178+
else:
3179+
# Note: This is equivalent to the behavior in stackplot
3180+
# TODO: do we want to be more restrictive and check lengths?
3181+
colors = itertools.cycle(colors)
3182+
31563183
bar_width = (group_distance /
31573184
(num_datasets + (num_datasets - 1) * bar_spacing + group_spacing))
31583185
bar_spacing_abs = bar_spacing * bar_width
@@ -3165,15 +3192,16 @@ def grouped_bar(self, x, heights, *, group_spacing=1.5, bar_spacing=0,
31653192

31663193
# place the bars, but only use numerical positions, categorical tick labels
31673194
# are handled separately below
3168-
for i, (hs, dataset_label) in enumerate(zip(heights, dataset_labels)):
3195+
for i, (hs, dataset_label, color) in enumerate(
3196+
zip(heights, dataset_labels, colors)):
31693197
lefts = (group_centers - 0.5 * group_distance + margin_abs
31703198
+ i * (bar_width + bar_spacing_abs))
31713199
if orientation == "vertical":
31723200
self.bar(lefts, hs, width=bar_width, align="edge",
3173-
label=dataset_label)
3201+
label=dataset_label, color=color, **kwargs)
31743202
else:
31753203
self.barh(lefts, hs, height=bar_width, align="edge",
3176-
label=dataset_label)
3204+
label=dataset_label, color=color, **kwargs)
31773205

31783206
if tick_labels is not None:
31793207
if orientation == "vertical":

lib/matplotlib/axes/_axes.pyi

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,18 @@ class Axes(_AxesBase):
279279
data=...,
280280
**kwargs
281281
) -> PolyCollection: ...
282+
def grouped_bar(
283+
self,
284+
x : ArrayLike,
285+
heights : ArrayLike,
286+
*,
287+
group_spacing : float | None = ...,
288+
bar_spacing : float | None = ...,
289+
dataset_labels : Sequence[str] | None = ...,
290+
orientation: Literal["vertical", "horizontal"] = ...,
291+
colors: Iterable[ColorType] | None = ...,
292+
**kwargs
293+
) -> None: ...
282294
def stem(
283295
self,
284296
*args: ArrayLike | str,

lib/matplotlib/pyplot.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3388,6 +3388,31 @@ def grid(
33883388
gca().grid(visible=visible, which=which, axis=axis, **kwargs)
33893389

33903390

3391+
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
3392+
@_copy_docstring_and_deprecators(Axes.grouped_bar)
3393+
def grouped_bar(
3394+
x: ArrayLike,
3395+
heights: ArrayLike,
3396+
*,
3397+
group_spacing: float | None = 1.5,
3398+
bar_spacing: float | None = 0,
3399+
dataset_labels: Sequence[str] | None = None,
3400+
orientation: Literal["vertical", "horizontal"] = "vertical",
3401+
colors: Iterable[ColorType] | None = None,
3402+
**kwargs,
3403+
) -> None:
3404+
gca().grouped_bar(
3405+
x,
3406+
heights,
3407+
group_spacing=group_spacing,
3408+
bar_spacing=bar_spacing,
3409+
dataset_labels=dataset_labels,
3410+
orientation=orientation,
3411+
colors=colors,
3412+
**kwargs,
3413+
)
3414+
3415+
33913416
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
33923417
@_copy_docstring_and_deprecators(Axes.hexbin)
33933418
def hexbin(

tools/boilerplate.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ def boilerplate_gen():
238238
'fill_between',
239239
'fill_betweenx',
240240
'grid',
241+
'grouped_bar',
241242
'hexbin',
242243
'hist',
243244
'stairs',

0 commit comments

Comments
 (0)