如何在 x 刻度上将多个条形图居中?

How to center multiple bar plots on x ticks?

我正在尝试绘制分组条形图,但条形图发生了偏移。在下面的示例中,我希望 x 刻度在绿色和橙色条之间居中,以便整个堆栈居中。

x = [56.35035714285714, 49.573170731707314, 48.100462962962965, 47.098684210526315, 44.452991452991455, 46.82525252525252, 46.99393939393939, 47.09538461538461, 46.35581395348837, 46.05, 46.38235294117647, 47.60588235294117, 42.7875, 44.25, 43.4]
y = [56.316428571428574, 51.560278745644595, 49.66481481481482, 48.367105263157896, 46.80427350427351, 49.59494949494949, 48.94242424242424, 48.395384615384614, 47.97674418604651, 45.86, 48.88823529411765, 48.48823529411764, 44.1875, 49.150000000000006, 44.76666666666667]
z = [59.60678571428572, 52.26794425087108, 51.4324074074074, 49.89934210526316, 47.705128205128204, 49.269696969696966, 49.35454545454546, 48.956923076923076, 48.36046511627907, 48.07, 50.33529411764705, 49.92941176470588, 45.65, 49.25, 46.43333333333334]
r = [59.59571428571428, 53.78989547038328, 52.50092592592593, 49.732236842105266, 48.32905982905983, 48.462626262626266, 49.306060606060605, 49.792307692307695, 48.37674418604651, 48.263333333333335, 49.95882352941176, 48.599999999999994, 45.7875, 50.2, 50.93333333333334]

import numpy as np
import matplotlib.pyplot as plt
x_labels = ["0-5","5-10","10-15","15-20","20-25","25,30","30-35","35-40","40-45","45-50","50-55","55,60","60-65","65,70","70-75"]

w=0.2

bar1 = np.arange(len(x_labels))

bar2 = [i+w for i in bar1 ]
bar3 = [i+w for i in bar2 ]
bar4 = [i+w for i in bar3 ]
plt.figure(figsize=(20,5))
plt.bar(bar1,x,w,label="A")
plt.bar(bar2,y,w,label="B")
plt.bar(bar3,z,w,label="C")
plt.bar(bar4,r,w,label="D")

plt.xlabel("x-axis")
plt.ylabel("y-axis")
plt.title("bar chart")
plt.xticks(bar1,x_labels)  

plt.legend()
  
plt.show()

输出:

由于您当前的条形图位置是相对于 bar1 定义的,最快的解决方法是将报价移动 1.5*w(其中 1.5 来自 number_of_groups/2 - 0.5):

plt.xticks(bar1 + 1.5*w, x_labels)

但这会将您的标记放在 non-standard 个位置 [0.3, 1.3, 2.3, ...](最终用户不可见,但可能更难以维护)。


更标准的方法是使用固定的 pivot 点并相对于 pivot 点移动 bar/tick 位置:

pivot = np.arange(len(x_labels))  # pivot points for bars/ticks
bar1 = [p - 1.5*w for p in pivot] # shift bars relative to pivot points
bar2 = [p - 0.5*w for p in pivot]
bar3 = [p + 0.5*w for p in pivot]
bar4 = [p + 1.5*w for p in pivot]
# ...
plt.xticks(pivot, x_labels)       # place ticks at pivot points, not bar1

或作为列表理解:

pivot = np.arange(len(x_labels))
bar1, bar2, bar3, bar4 = [[p + k*w for p in pivot] for k in (-1.5, -0.5, 0.5, 1.5)]
# ...
plt.xticks(pivot, x_labels)

完整代码:

x = [56.35035714285714, 49.573170731707314, 48.100462962962965, 47.098684210526315, 44.452991452991455, 46.82525252525252, 46.99393939393939, 47.09538461538461, 46.35581395348837, 46.05, 46.38235294117647, 47.60588235294117, 42.7875, 44.25, 43.4]
y = [56.316428571428574, 51.560278745644595, 49.66481481481482, 48.367105263157896, 46.80427350427351, 49.59494949494949, 48.94242424242424, 48.395384615384614, 47.97674418604651, 45.86, 48.88823529411765, 48.48823529411764, 44.1875, 49.150000000000006, 44.76666666666667]
z = [59.60678571428572, 52.26794425087108, 51.4324074074074, 49.89934210526316, 47.705128205128204, 49.269696969696966, 49.35454545454546, 48.956923076923076, 48.36046511627907, 48.07, 50.33529411764705, 49.92941176470588, 45.65, 49.25, 46.43333333333334]
r = [59.59571428571428, 53.78989547038328, 52.50092592592593, 49.732236842105266, 48.32905982905983, 48.462626262626266, 49.306060606060605, 49.792307692307695, 48.37674418604651, 48.263333333333335, 49.95882352941176, 48.599999999999994, 45.7875, 50.2, 50.93333333333334]

import numpy as np
import matplotlib.pyplot as plt
x_labels = ['0-5', '5-10', '10-15', '15-20', '20-25', '25-30', '30-35', '35-40', '40-45', '45-50', '50-55', '55-60', '60-65', '65-70', '70-75']

w = 0.2

pivot = np.arange(len(x_labels)) # pivot points for bars/ticks
bar1, bar2, bar3, bar4 = [[p + k*w for p in pivot] for k in (-1.5, -0.5, 0.5, 1.5)]

plt.figure(figsize=(20, 5))
plt.bar(bar1, x, w, label='A')
plt.bar(bar2, y, w, label='B')
plt.bar(bar3, z, w, label='C')
plt.bar(bar4, r, w, label='D')

plt.xlabel('x-axis')
plt.ylabel('y-axis')
plt.title('bar chart')
plt.xticks(pivot, x_labels) # place ticks at pivot points, not bar1

plt.legend()

plt.show()