Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 93c7651

Browse filesBrowse files
committed
Add group and bar spacing
1 parent f47d748 commit 93c7651
Copy full SHA for 93c7651

File tree

2 files changed

+76
-6
lines changed
Filter options

2 files changed

+76
-6
lines changed

‎galleries/examples/lines_bars_and_markers/grouped_bar_chart.py

Copy file name to clipboardExpand all lines: galleries/examples/lines_bars_and_markers/grouped_bar_chart.py
+40Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,43 @@
118118

119119
fig, ax = plt.subplots()
120120
ax.grouped_bar(x, data)
121+
122+
123+
# %%
124+
# Bar width and spacing
125+
# ---------------------
126+
# The center positions of the bar groups are given by x. We can still choose
127+
# two of the following properties: bar width, spacing between groups, and
128+
# spacing between bars.
129+
#
130+
# We believe the most convenient approach is defining spacing between groups
131+
# and spacing between bars as fraction of the bar width.
132+
133+
x = ['A', 'B', 'C']
134+
data = {
135+
'data1': [1, 2, 3],
136+
'data2': [1.2, 2.2, 3.2],
137+
'data3': [1.4, 2.4, 3.4],
138+
'data4': [1.6, 2.6, 3.6],
139+
}
140+
141+
fig, axs = plt.subplots(2, 2)
142+
ax[0, 0].grouped_bar(x, data)
143+
ax[0, 1].grouped_bar(x, data, group_spacing=0.5)
144+
ax[1, 0].grouped_bar(x, data, bar_spacing=0.2)
145+
ax[1, 1].grouped_bar(x, data, group_spacing=0.5, bar_spacing=0.1)
146+
147+
148+
# %%
149+
# Horizontal grouped bars
150+
# -----------------------
151+
# Use ``orientation="horizontal"`` to create horizontal grouped bar charts.
152+
153+
x = ['A', 'B', 'C']
154+
data = {
155+
'data1': [1, 2, 3],
156+
'data2': [1.2, 2.2, 3.2],
157+
}
158+
159+
fig, ax = plt.subplots()
160+
ax.grouped_bar(x, data, orientation="horizontal")

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+36-6Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,7 +3013,8 @@ def broken_barh(self, xranges, yrange, **kwargs):
30133013

30143014
return col
30153015

3016-
def grouped_bar(self, x, heights, dataset_labels=None):
3016+
def grouped_bar(self, x, heights, *, group_spacing=1.5, bar_spacing=0,
3017+
dataset_labels=None, orientation="vertical"):
30173018
"""
30183019
Parameters
30193020
-----------
@@ -3069,9 +3070,20 @@ def grouped_bar(self, x, heights, dataset_labels=None):
30693070
30703071
An iterable of array-like: The iteration runs over the groups.
30713072
Each individual array-like is the list of label values for that group.
3073+
3074+
group_spacing : float
3075+
The space between two bar groups in units of bar width.
3076+
3077+
bar_spacing : float
3078+
The space between bars in units of bar width.
3079+
30723080
dataset_labels : array-like of str, optional
30733081
The labels of the datasets.
3082+
3083+
orientation : {"vertical", "horizontal"}, default: vertical
30743084
"""
3085+
_api.check_in_list(["vertical", "horizontal"], orientation=orientation)
3086+
30753087
if hasattr(heights, 'keys'):
30763088
if dataset_labels is not None:
30773089
raise ValueError(
@@ -3087,11 +3099,15 @@ def grouped_bar(self, x, heights, dataset_labels=None):
30873099
if isinstance(x[0], str):
30883100
tick_labels = x
30893101
group_centers = np.arange(num_groups)
3102+
group_distance = 1
30903103
else:
30913104
if num_groups > 1:
30923105
d = np.diff(x)
30933106
if not np.allclose(d, d.mean()):
30943107
raise ValueError("'x' must be equidistant")
3108+
group_distance = d[0]
3109+
else:
3110+
group_distance = 1
30953111
group_centers = np.asarray(x)
30963112
tick_labels = None
30973113

@@ -3102,19 +3118,33 @@ def grouped_bar(self, x, heights, dataset_labels=None):
31023118
f"has {len(dataset)} groups"
31033119
)
31043120

3105-
margin = 0.1
3106-
bar_width = (1 - 2 * margin) / num_datasets
3121+
bar_width = (group_distance /
3122+
(num_datasets + (num_datasets - 1) * bar_spacing + group_spacing))
3123+
bar_spacing_abs = bar_spacing * bar_width
3124+
margin_abs = 0.5 * group_spacing * bar_width
31073125

31083126
if dataset_labels is None:
31093127
dataset_labels = [None] * num_datasets
31103128
else:
31113129
assert len(dataset_labels) == num_datasets
31123130

3131+
# place the bars, but only use numerical positions, categorical tick labels
3132+
# are handled separately below
31133133
for i, (hs, dataset_label) in enumerate(zip(heights, dataset_labels)):
3114-
lefts = group_centers - 0.5 + margin + i * bar_width
3115-
self.bar(lefts, hs, width=bar_width, align="edge", label=dataset_label)
3134+
lefts = (group_centers - 0.5 * group_distance + margin_abs
3135+
+ i * (bar_width + bar_spacing_abs))
3136+
if orientation == "vertical":
3137+
self.bar(lefts, hs, width=bar_width, align="edge",
3138+
label=dataset_label)
3139+
else:
3140+
self.barh(lefts, hs, height=bar_width, align="edge",
3141+
label=dataset_label)
31163142

3117-
self.xaxis.set_ticks(group_centers, labels=tick_labels)
3143+
if tick_labels is not None:
3144+
if orientation == "vertical":
3145+
self.xaxis.set_ticks(group_centers, labels=tick_labels)
3146+
else:
3147+
self.yaxis.set_ticks(group_centers, labels=tick_labels)
31183148

31193149
# TODO: does not return anything for now
31203150

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.