8000 Add support for numeric x · matplotlib/matplotlib@f47d748 · GitHub
[go: up one dir, main page]

Skip to content

Commit f47d748

Browse files
committed
Add support for numeric x
1 parent d8847ec commit f47d748

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

galleries/examples/lines_bars_and_markers/grouped_bar_chart.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,19 @@
102102
#
103103
# df = pd.DataFrame(data, index=x, columns=columns)
104104
# df.plot.bar()
105+
106+
# %%
107+
# Numeric x values
108+
# ----------------
109+
# In the most common case, one will want to pass categorical labels as *x*.
110+
# Additionally, we allow numeric values for *x*, as with `~.Axes.bar()`.
111+
# But for simplicity and clarity, we require that these are equidistant.
112+
113+
x = [0, 2, 4]
114+
data = {
115+
'data1': [1, 2, 3],
116+
'data2': [1.2, 2.2, 3.2],
117+
}
118+
119+
fig, ax = plt.subplots()
120+
ax.grouped_bar(x, data)

lib/matplotlib/axes/_axes.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3017,8 +3017,12 @@ def grouped_bar(self, x, heights, dataset_labels=None):
30173017
"""
30183018
Parameters
30193019
-----------
3020-
x : array-like of str
3021-
The labels.
3020+
x : array-like or list of str
3021+
The center positions of the bar groups. If these are numeric values,
3022+
they have to be equidistant. As with `~.Axes.bar`, you can provide
3023+
categorical labels, which will be used at integer numeric positions
3024+
``range(x)``.
3025+
30223026
heights : list of array-like or dict of array-like or 2D array
30233027
The heights for all x and groups. One of:
30243028
@@ -3077,27 +3081,40 @@ def grouped_bar(self, x, heights, dataset_labels=None):
30773081
elif hasattr(heights, 'shape'):
30783082
heights = heights.T
30793083

3080-
num_labels = len(x)
3084+
num_groups = len(x)
30813085
num_datasets = len(heights)
30823086

3083-
for dataset in heights:
3084-
assert len(dataset) == num_labels
3087+
if isinstance(x[0], str):
3088+
tick_labels = x
3089+
group_centers = np.arange(num_groups)
3090+
else:
3091+
if num_groups > 1:
3092+
d = np.diff(x)
3093+
if not np.allclose(d, d.mean()):
3094+
raise ValueError("'x' must be equidistant")
3095+
group_centers = np.asarray(x)
3096+
tick_labels = None
3097+
3098+
for i, dataset in enumerate(heights):
3099+
if len(dataset) != num_groups:
3100+
raise ValueError(
3101+
f"'x' indicates {num_groups} groups, but dataset {i} "
3102+
f"has {len(dataset)} groups"
3103+
)
30853104

30863105
margin = 0.1
30873106
bar_width = (1 - 2 * margin) / num_datasets
3088-
block_centers = np.arange(num_labels)
30893107

30903108
if dataset_labels is None:
30913109
dataset_labels = [None] * num_datasets
30923110
else:
30933111
assert len(dataset_labels) == num_datasets
30943112

30953113
for i, (hs, dataset_label) in enumerate(zip(heights, dataset_labels)):
3096-
lefts = block_centers - 0.5 + margin + i * bar_width
3097-
print(i, x, lefts, hs, dataset_label)
3114+
lefts = group_centers - 0.5 + margin + i * bar_width
30983115
self.bar(lefts, hs, width=bar_width, align="edge", label=dataset_label)
30993116

3100-
self.xaxis.set_ticks(block_centers, labels=x)
3117+
self.xaxis.set_ticks(group_centers, labels=tick_labels)
31013118

31023119
# TODO: does not return anything for now
31033120

0 commit comments

Comments
 (0)
0