@@ -2506,6 +2506,7 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
25062506 See Also
25072507 --------
25082508 barh : Plot a horizontal bar plot.
2509+ grouped_bar : Plot multiple datasets as grouped bar plot.
25092510
25102511 Notes
25112512 -----
@@ -3073,17 +3074,27 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
30733074 Make a grouped bar plot.
30743075
30753076 .. note::
3076- This function is new in v3.10 , and the API is still provisional.
3077+ This function is new in v3.11 , and the API is still provisional.
30773078 We may still fine-tune some aspects based on user-feedback.
30783079
30793080 This is a convenience function to plot bar charts for multiple datasets
30803081 into one Axes. In particular, it simplifies positioning of the bars
30813082 compared to individual `~.Axes.bar` plots.
30823083
3083- Terminology: A bar *group* is a set of bars drawn next to each other. They
3084- can be associated with a group name, which is visualized as the tick label
3085- below that group. A *dataset* is a set of values, one for each bar group.
3086- This means *dataset_0* will be rendered as the first bar in each bar group.
3084+ 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
3086+ color. Grouped bar plots show multiple such datasets, where the values per
3087+ category are grouped together. The category names are drawn as a tick labels
3088+ below the bar groups. Each dataset has a distinct bar color, and can optionally
3089+ get a label that is used for the legend.
3090+
3091+ Here is an example call structure and the corresponding plot:
3092+
3093+ .. code-block:: python
3094+
3095+ grouped_bar([dataset_1, dataset_2, dataset_3],
3096+ tick_labels=['A', 'B'],
3097+ labels=['dataset 1', 'dataset 2', 'dataset 3'])
30873098
30883099 .. plot:: _embedded_plots/grouped_bar.py
30893100
@@ -3097,60 +3108,67 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
30973108
30983109 .. code-block:: none
30993110
3100- # group_A group_B
3101- dataset_0 = [ds0_a, ds0_b]
3102- dataset_1 = [ds1_a, ds1_b]
3103- dataset_2 = [ds2_a, ds2_b]
3104-
3105- heights = [dataset_0, dataset_1, dataset_2]
3111+ # category_A, category_B
3112+ dataset_0 = [ds0_A, ds0_B]
3113+ dataset_1 = [ds1_A, ds1_B]
3114+ dataset_2 = [ds2_A, ds2_B]
31063115
31073116 Example call::
31083117
31093118 grouped_bar([dataset_0, dataset_1, dataset_2])
31103119
3111- - dict of array-like: A mapping names to datasets. Each dataset
3112- (dict value) must have the same number of elements elements .
3120+ - dict of array-like: A mapping from names to datasets. Each dataset
3121+ (dict value) must have the same number of elements.
31133122
31143123 This is similar to passing a list of array-like, with the addition that
31153124 each dataset gets a name.
31163125
3117- Example call::
3126+ Example call:
3127+
3128+ .. code-block:: python
31183129
31193130 grouped_bar({'ds0': dataset_0, 'ds1': dataset_1, 'ds2': dataset_2]})
31203131
31213132 The names are used as *labels*, i.e. the following two calls are
3122- equivalent::
3133+ equivalent:
3134+
3135+ .. code-block:: python
31233136
31243137 data_dict = {'ds0': dataset_0, 'ds1': dataset_1, 'ds2': dataset_2]}
31253138 grouped_bar(data_dict)
31263139 grouped_bar(data_dict.values(), labels=data_dict.keys())
31273140
31283141 When using a dict-like input, you must not pass *labels* explicitly.
31293142
3130- - a 2D array: The columns are the different datasets.
3143+ - a 2D array: The rows are the categories, the columns are the different
3144+ datasets.
31313145
31323146 .. code-block:: none
31333147
3134- dataset_0 dataset_1 dataset_2
3135- group_A ds0_a ds1_a ds2_a
3136- group_B ds0_b ds1_b ds2_b
3148+ dataset_0 dataset_1 dataset_2
3149+ category_A ds0_a ds1_a ds2_a
3150+ category_B ds0_b ds1_b ds2_b
3151+
3152+ Example call:
31373153
3138- .. code-block::
3154+ .. code-block:: python
31393155
31403156 group_labels = ["group_A", "group_B"]
31413157 dataset_labels = ["dataset_0", "dataset_1", "dataset_2"]
31423158 array = np.random.random((2, 3))
31433159
31443160 Note that this is consistent with pandas. These two calls produce
3145- the same bar plot structure::
3161+ the same bar plot structure:
31463162
3147- grouped_bar(array, tick_labels=group_labels, labels=dataset_labels)
3148- df = pd.DataFrame(array, index=group_labels, columns=dataset_labels)
3163+ .. code-block:: python
3164+
3165+ grouped_bar(array, tick_labels=categories, labels=dataset_labels)
3166+ df = pd.DataFrame(array, index=categories, columns=dataset_labels)
31493167 df.plot.bar()
31503168
31513169 - a `pandas.DataFrame`.
31523170
3153- .. code-block::
3171+ .. code-block:: python
31543172
31553173 df = pd.DataFrame(
31563174 np.random.random((2, 3))
@@ -3159,15 +3177,15 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
31593177 )
31603178 grouped_bar(df)
31613179
3162- Note that ``grouped_bar(df)`` produced a structurally equivalent plot like
3163- ``df.plot.bar()`.
3180+ Note that ``grouped_bar(df)`` produces a structurally equivalent plot like
3181+ ``df.plot.bar()`` .
31643182
31653183 positions : array-like, optional
31663184 The center positions of the bar groups. The values have to be equidistant.
31673185 If not given, a sequence of integer positions 0, 1, 2, ... is used.
31683186
31693187 tick_labels: list of str, optional
3170- The group labels, which are placed on ticks at the center *positions*
3188+ The category labels, which are placed on ticks at the center *positions*
31713189 of the bar groups.
31723190
31733191 If not set, the axis ticks (positions and labels) are left unchanged.
@@ -3202,7 +3220,7 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
32023220 _GroupedBarReturn
32033221
32043222 A provisional result object. This will be refined in the future.
3205- For now, the API is limited to
3223+ For now, the guaranteed API on the returned object is limited to
32063224
32073225 - the attribute ``bar_containers``, which is a list of
32083226 `.BarContainer`, i.e. the results of the individual `~.Axes.bar`
@@ -3211,6 +3229,65 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
32113229 - a ``remove()`` method, that remove all bars from the Axes.
32123230 See also `.Artist.remove()`.
32133231
3232+ See Also
3233+ --------
3234+ bar : A lower-level API for bar plots, with more degrees of freedom like
3235+ individal bar sizes and colors.
3236+
3237+ Notes
3238+ -----
3239+ For a better understanding, we compare the `~.Axes.grouped_bar` API with
3240+ those of `~.Axes.bar` and `~.Axes.boxplot`.
3241+
3242+ **Comparison to ``bar()``**
3243+
3244+ ``grouped_bar`` intentionally deviates from the `~.Axes.bar()` API in some
3245+ aspects. ``bar(x, y)`` is a lower-level API and places bars with height *y*
3246+ at explicit positions *x*. It also allows to specify individual bar widths
3247+ and colors. This kind of detailed control and flexibility is difficult to
3248+ manage and often not needed when plotting multiple datasets as grouped bar
3249+ plots. Therefore, ``grouped_bar`` focusses on the abstraction of bar plots
3250+ as visualization of categorical data.
3251+
3252+ The following examples may help to transfer from ``bar()`` to
3253+ ``grouped_bar()``.
3254+
3255+ Pasitions are deemphasized due to categories, and default to integer values.
3256+ If you have used ``range(N)`` as positions, you can leave that value out::
3257+
3258+ bar(range(N), heights)
3259+ grouped_bar([heights])
3260+
3261+ If needed, positions can be passed as keyword arguments::
3262+
3263+ bar(x, heights)
3264+ grouped_bar(heights, positions=x)
3265+
3266+ To place category labels in ``bar()`` you could use the argument
3267+ *tick_label* or use a list of cateogry names as *x*. ``grouped_bar()``
3268+ expects them in the argument *tick_labels*::
3269+
3270+ bar(range(N), heights, tick_label=["A", "B"])
3271+ bar(["A", "B"], heights)
3272+ grouped_bar([heights], tick_labels=["A", "B"])
3273+
3274+ Dataset labels that are shown in the legend are still passed via the
3275+ *label* parameter::
3276+
3277+ bar(..., label="dataset")
3278+ grouped_bar(..., label=["dataset"])
3279+
3280+ **Comparison to ``boxplot()``**
3281+
3282+ Both, `~.Axes.grouped_bar()` and `.Axes.boxplot()` visualize categorical
3283+ from multiple datasets. The basic API on *tick_labels* and *positions*
3284+ is the same, so that you can easily switch between plotting all
3285+ individual values as ``grouped_bar()`` or the statistical distribution
3286+ per category as ``boxplot()``::
3287+
3288+ grouped_bar(values, positions=..., tick_labels=...)
3289+ boxplot(values, positions=..., tick_labels=...)
3290+
32143291 """
32153292 if cbook ._is_pandas_dataframe (heights ):
32163293 if labels is None :
0 commit comments