如何缩小Matplotlib中x轴刻度间距及调整柱状图边距?
问题描述
我已查阅相关资料但其中解答无法解决我的问题。我编写了生成4幅子图的Matplotlib代码如下:
import matplotlib.pyplot as plt import numpy as np group_x = [5, 0, 1, 16, 3, 1, 2, 0, 8, 2, 11, 5] group_y = [8, 10, 6, 0, 0, 5, 12, 0, 14, 2, 1, 7] group_w = [1, 3, 13, 9, 0, 15, 6, 2, 3, 7, 1, 0] group_z = [0, 1, 2, 0, 10, 12, 12, 0, 8, 12, 4, 6] ranges = ['a', '(a, b)', '(b, c)', '(c, d)', '(d, e)', '(e, f)', '(f, g)', '(g, h)', '(h, i)', '(i, j)', '(j, k)', 'k'] colors = ['red', 'blue', 'green', 'purple'] participants = ['Group X', 'Group Y', 'Group W', 'Group Z'] fig, axes = plt.subplots(2, 2, figsize=(12, 5)) c = 0 for i, ax_row in enumerate(axes): for j, ax in enumerate(ax_row): data = [group_x, group_y, group_w, group_z][c] ax.text(.5, .9, f'{participants[i]}', horizontalalignment='center', transform=ax.transAxes) bars = ax.bar(ranges, data, color=colors[c], width=0.2) ax.set_yticks(np.arange(0, 21, 5)) ax.set_yticklabels(range(0, 21, 5), fontsize=9) ax.set_xticks(np.arange(12)) ax.set_xticklabels(ranges, rotation=30, ha='right', fontsize=8.5) ax.set_xlabel('Characters') ax.set_ylabel('Frequency', fontsize=8) for bar, score in zip(bars, data): ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height(), str(score), ha='center', va='bottom') c += 1 plt.tight_layout() plt.savefig('stackover.png', dpi=600, bbox_inches='tight') plt.show()
当前生成的图表效果:
我希望缩小x轴刻度间的间距,使柱状图与对应x轴刻度紧密相邻,同时让对应'a'的柱状图贴近y轴,对应'k'的柱状图贴近子图右边缘,请问如何修改代码实现这些效果?
解决方案
要实现需求,需调整x轴刻度控制逻辑和柱子宽度,具体修改如下:
核心修改点
- 改用数值型x轴位置,替换原字符串标签的自动布局,精确控制刻度间距
- 增大柱子宽度,让柱子与刻度更贴合
- 设置x轴范围,强制首尾柱子贴紧子图边缘
- 修正原代码中标题引用的错误
修改后的完整代码
import matplotlib.pyplot as plt import numpy as np group_x = [5, 0, 1, 16, 3, 1, 2, 0, 8, 2, 11, 5] group_y = [8, 10, 6, 0, 0, 5, 12, 0, 14, 2, 1, 7] group_w = [1, 3, 13, 9, 0, 15, 6, 2, 3, 7, 1, 0] group_z = [0, 1, 2, 0, 10, 12, 12, 0, 8, 12, 4, 6] ranges = ['a', '(a, b)', '(b, c)', '(c, d)', '(d, e)', '(e, f)', '(f, g)', '(g, h)', '(h, i)', '(i, j)', '(j, k)', 'k'] colors = ['red', 'blue', 'green', 'purple'] participants = ['Group X', 'Group Y', 'Group W', 'Group Z'] fig, axes = plt.subplots(2, 2, figsize=(12, 5)) c = 0 for i, ax_row in enumerate(axes): for j, ax in enumerate(ax_row): data = [group_x, group_y, group_w, group_z][c] # 修正标题引用错误,用c索引对应分组 ax.text(.5, .9, f'{participants[c]}', horizontalalignment='center', transform=ax.transAxes) # 生成数值型x轴位置,替代原字符串标签 x = np.arange(len(ranges)) # 增大柱子宽度到0.8,缩小刻度间空白 bars = ax.bar(x, data, color=colors[c], width=0.8) ax.set_yticks(np.arange(0, 21, 5)) ax.set_yticklabels(range(0, 21, 5), fontsize=9) # 把刻度精准放在每个柱子的中心位置 ax.set_xticks(x) ax.set_xticklabels(ranges, rotation=30, ha='right', fontsize=8.5) ax.set_xlabel('Characters') ax.set_ylabel('Frequency', fontsize=8) # 设置x轴范围,让首尾柱子贴紧子图边缘 ax.set_xlim(-0.4, len(x)-0.6) for bar, score in zip(bars, data): ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height(), str(score), ha='center', va='bottom') c += 1 plt.tight_layout() plt.savefig('stackover.png', dpi=600, bbox_inches='tight') plt.show()
关键说明
- 数值型x轴
np.arange(len(ranges))让刻度位置完全可控,避免字符串标签的自动间距 - 柱子宽度设为0.8(最大值为1,代表刻度间无空白),让柱子与刻度紧密对齐
ax.set_xlim(-0.4, len(x)-0.6):因柱子宽度为0.8,左边界设为-0.4让第一个柱子左边缘对齐y轴;右边界设为len(x)-0.6让最后一个柱子右边缘对齐子图右边缘- 修正了原代码中标题引用的错误,确保每个子图标题对应正确分组
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

