Skip to content

Commit 162ce79

Browse files
timhoffmstory645
andcommitted
Apply suggestions from code review
Co-authored-by: hannah <story645@gmail.com>
1 parent bf2894a commit 162ce79

File tree

2 files changed

+42
-46
lines changed

2 files changed

+42
-46
lines changed

doc/users/next_whats_new/grouped_bar.rst

+5-4
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ Example:
1010

1111
.. plot::
1212
:include-source: true
13+
:alt: Diagram of a grouped bar chart of 3 datasets with 2 categories.
1314

1415
import matplotlib.pyplot as plt
1516

1617
categories = ['A', 'B']
1718
datasets = {
18-
'dataset 0': [1.0, 3.0],
19-
'dataset 1': [1.4, 3.4],
20-
'dataset 2': [1.8, 3.8],
19+
'dataset 0': [1, 11],
20+
'dataset 1': [3, 13],
21+
'dataset 2': [5, 15],
2122
}
2223

23-
fig, ax = plt.subplots(figsize=(4, 2.2))
24+
fig, ax = plt.subplots()
2425
ax.grouped_bar(datasets, tick_labels=categories)
2526
ax.legend()

lib/matplotlib/axes/_axes.py

+37-42
Original file line numberDiff line numberDiff line change
@@ -3073,22 +3073,19 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
30733073
"""
30743074
Make a grouped bar plot.
30753075
3076-
.. note::
3076+
.. versionadded:: 3.11
3077+
30773078
This function is new in v3.11, and the API is still provisional.
30783079
We may still fine-tune some aspects based on user-feedback.
30793080
3080-
This is a convenience function to plot bars for multiple datasets.
3081-
In particular, it simplifies positioning of the bars compared to individual
3082-
`~.Axes.bar` plots.
3083-
30843081
Bar plots present categorical data as a sequence of bars, one bar per category.
3085-
We call one set of such values a *dataset* and it's bars all share the same
3082+
We call one set of such values a *dataset* and its bars all share the same
30863083
color. Grouped bar plots show multiple such datasets, where the values per
30873084
category are grouped together. The category names are drawn as tick labels
30883085
below the bar groups. Each dataset has a distinct bar color, and can optionally
30893086
get a label that is used for the legend.
30903087
3091-
Here is an example call structure and the corresponding plot:
3088+
Example:
30923089
30933090
.. code-block:: python
30943091
@@ -3121,25 +3118,20 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
31213118
- dict of array-like: A mapping from names to datasets. Each dataset
31223119
(dict value) must have the same number of elements.
31233120
3124-
This is similar to passing a list of array-like, with the addition that
3125-
each dataset gets a name.
3126-
31273121
Example call:
31283122
31293123
.. code-block:: python
31303124
3131-
grouped_bar({'ds0': dataset_0, 'ds1': dataset_1, 'ds2': dataset_2]})
3125+
data_dict = {'ds0': dataset_0, 'ds1': dataset_1, 'ds2': dataset_2}
3126+
grouped_bar(data_dict)
31323127
3133-
The names are used as *labels*, i.e. the following two calls are
3134-
equivalent:
3128+
The names are used as *labels*, i.e. this is equivalent to
31353129
31363130
.. code-block:: python
31373131
3138-
data_dict = {'ds0': dataset_0, 'ds1': dataset_1, 'ds2': dataset_2]}
3139-
grouped_bar(data_dict)
31403132
grouped_bar(data_dict.values(), labels=data_dict.keys())
31413133
3142-
When using a dict-like input, you must not pass *labels* explicitly.
3134+
When using a dict input, you must not pass *labels* explicitly.
31433135
31443136
- a 2D array: The rows are the categories, the columns are the different
31453137
datasets.
@@ -3154,30 +3146,31 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
31543146
31553147
.. code-block:: python
31563148
3157-
group_labels = ["group_A", "group_B"]
3149+
categories = ["A", "B"]
31583150
dataset_labels = ["dataset_0", "dataset_1", "dataset_2"]
31593151
array = np.random.random((2, 3))
3160-
3161-
Note that this is consistent with pandas. These two calls produce
3162-
the same bar plot structure:
3163-
3164-
.. code-block:: python
3165-
31663152
grouped_bar(array, tick_labels=categories, labels=dataset_labels)
3167-
df = pd.DataFrame(array, index=categories, columns=dataset_labels)
3168-
df.plot.bar()
31693153
31703154
- a `pandas.DataFrame`.
31713155
3156+
The index is used for the categories, the columns are used for the
3157+
datasets.
3158+
31723159
.. code-block:: python
31733160
31743161
df = pd.DataFrame(
3175-
np.random.random((2, 3))
3176-
index=["group_A", "group_B"],
3162+
np.random.random((2, 3)),
3163+
index=["A", "B"],
31773164
columns=["dataset_0", "dataset_1", "dataset_2"]
31783165
)
31793166
grouped_bar(df)
31803167
3168+
i.e. this is equivalent to
3169+
3170+
.. code-block::
3171+
3172+
grouped_bar(df.to_numpy(), tick_labels=df.index, labels=df.columns)
3173+
31813174
Note that ``grouped_bar(df)`` produces a structurally equivalent plot like
31823175
``df.plot.bar()``.
31833176
@@ -3187,22 +3180,21 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
31873180
31883181
tick_labels : list of str, optional
31893182
The category labels, which are placed on ticks at the center *positions*
3190-
of the bar groups.
3191-
3192-
If not set, the axis ticks (positions and labels) are left unchanged.
3183+
of the bar groups. If not set, the axis ticks (positions and labels) are
3184+
left unchanged.
31933185
31943186
labels : list of str, optional
31953187
The labels of the datasets, i.e. the bars within one group.
31963188
These will show up in the legend.
31973189
31983190
group_spacing : float, default: 1.5
3199-
The space between two bar groups in units of bar width.
3191+
The space between two bar groups as multiples of bar width.
32003192
32013193
The default value of 1.5 thus means that there's a gap of
32023194
1.5 bar widths between bar groups.
32033195
32043196
bar_spacing : float, default: 0
3205-
The space between bars in units of bar width.
3197+
The space between bars as multiples of bar width.
32063198
32073199
orientation : {"vertical", "horizontal"}, default: "vertical"
32083200
The direction of the bars.
@@ -3249,7 +3241,7 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
32493241
aspects. ``bar(x, y)`` is a lower-level API and places bars with height *y*
32503242
at explicit positions *x*. It also allows to specify individual bar widths
32513243
and colors. This kind of detailed control and flexibility is difficult to
3252-
manage and often not needed when plotting multiple datasets as grouped bar
3244+
manage and often not needed when plotting multiple datasets as a grouped bar
32533245
plot. Therefore, ``grouped_bar`` focusses on the abstraction of bar plots
32543246
as visualization of categorical data.
32553247
@@ -3309,8 +3301,18 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
33093301
heights = heights.T
33103302

33113303
num_datasets = len(heights)
3312-
dataset_0 = next(iter(heights))
3313-
num_groups = len(dataset_0)
3304+
num_groups = len(next(iter(heights))) # inferred from first dataset
3305+
3306+
# validate that all datasets have the same length, i.e. num_groups
3307+
# - can be skipped if heights is an array
3308+
if not hasattr(heights, 'shape'):
3309+
for i, dataset in enumerate(heights):
3310+
if len(dataset) != num_groups:
3311+
raise ValueError(
3312+
"'heights' contains datasets with different number of "
3313+
f"elements. dataset 0 has {num_groups} elements but "
3314+
f"dataset {i} has {len(dataset)} elements."
3315+
)
33143316

33153317
if positions is None:
33163318
group_centers = np.arange(num_groups)
@@ -3325,13 +3327,6 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
33253327
else:
33263328
group_distance = 1
33273329

3328-
for i, dataset in enumerate(heights):
3329-
if len(dataset) != num_groups:
3330-
raise ValueError(
3331-
f"'x' indicates {num_groups} groups, but dataset {i} "
3332-
f"has {len(dataset)} groups"
3333-
)
3334-
33353330
_api.check_in_list(["vertical", "horizontal"], orientation=orientation)
33363331

33373332
if colors is None:

0 commit comments

Comments
 (0)