柱状图(垂直条形图)是展示分类数据对比的经典图表,用矩形柱的高度表示数值大小。
Matplotlib 的 plt.bar() 函数提供了灵活的柱状图绘制能力,支持分组、堆叠、误差线等高级功能。
最简单的柱状图:传入类别名称和对应的数值:
import matplotlib.pyplot as plt
categories = ['北京', '上海', '广州', '深圳']
values = [210, 290, 180, 250]
plt.bar(categories, values)
plt.title('基础柱状图 - 城市销售额')
plt.xlabel('城市')
plt.ylabel('销售额 (万元)')
plt.show()
bar() 支持丰富的样式参数:
| 参数 | 说明 | 示例 |
|---|---|---|
color | 柱体颜色(可统一或序列) | color='steelblue' 或 color=['red','green','blue'] |
edgecolor | 边框颜色 | edgecolor='black' |
linewidth | 边框线宽 | linewidth=1.5 |
width | 柱宽 (0~1之间,默认0.8) | width=0.6 |
alpha | 透明度 | alpha=0.7 |
categories = ['A', 'B', 'C', 'D']
values = [25, 40, 30, 35]
plt.bar(categories, values,
color='lightcoral',
edgecolor='darkred',
linewidth=2,
width=0.5,
alpha=0.8)
plt.title('定制样式的柱状图')
plt.show()
用于比较多个系列在同一类别下的数值。通过调整柱子的 x 坐标位置实现:
import numpy as np
categories = ['2019', '2020', '2021', '2022']
series1 = [20, 25, 32, 38] # 产品A
series2 = [18, 22, 28, 35] # 产品B
series3 = [15, 20, 25, 30] # 产品C
x = np.arange(len(categories)) # [0,1,2,3]
width = 0.25
fig, ax = plt.subplots(figsize=(10, 6))
bars1 = ax.bar(x - width, series1, width, label='产品A', color='#1f77b4')
bars2 = ax.bar(x, series2, width, label='产品B', color='#ff7f0e')
bars3 = ax.bar(x + width, series3, width, label='产品C', color='#2ca02c')
ax.set_xlabel('年份')
ax.set_ylabel('销量 (万件)')
ax.set_title('分组柱状图 - 各产品年度销量')
ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend()
plt.show()
x - width, x, x + width 实现三组并排。使用 bottom 参数将多个系列上下堆叠,展示总量与构成:
categories = ['Q1', 'Q2', 'Q3', 'Q4']
online = [12, 15, 14, 18]
offline = [10, 12, 11, 15]
plt.bar(categories, online, label='线上', color='#4CAF50')
plt.bar(categories, offline, bottom=online, label='线下', color='#FF9800')
plt.title('堆叠柱状图 - 各季度销售额构成')
plt.ylabel('销售额 (万元)')
plt.legend()
plt.show()
bottom 参数指定第二个系列的起始高度为第一个系列的高度。遍历柱体对象,使用 text() 在柱顶添加数值:
categories = ['A', 'B', 'C', 'D']
values = [25, 40, 30, 35]
bars = plt.bar(categories, values, color='skyblue', edgecolor='black')
# 添加数据标签
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height + 0.5,
f'{height}', ha='center', va='bottom', fontsize=10)
plt.title('带数据标签的柱状图')
plt.ylim(0, max(values) * 1.1) # 预留标签空间
plt.show()
适用于展示数据的变异范围(如标准差、标准误):
categories = ['A', 'B', 'C', 'D']
means = [25, 40, 30, 35]
errors = [3, 5, 2, 4] # 误差幅度
plt.bar(categories, means, yerr=errors, capsize=5,
color='lightgreen', edgecolor='darkgreen', linewidth=1.5,
error_kw={'elinewidth': 2, 'ecolor': 'red'}) # 误差线样式
plt.title('带误差线的柱状图')
plt.show()
yerr 指定垂直误差,capsize 控制端帽大小。当类别名称较长时,可以旋转 x 轴刻度避免重叠:
categories = ['非常长的类别名称A', '非常长的类别名称B', '非常长的类别名称C', '非常长的类别名称D']
values = [25, 40, 30, 35]
plt.bar(categories, values)
plt.xticks(rotation=45, ha='right') # 旋转45度,右对齐
plt.title('旋转标签避免重叠')
plt.tight_layout() # 自动调整边距
plt.show()
如果类别名称很长,水平柱状图(barh)是更好的选择:
categories = ['电子产品', '服装鞋帽', '食品饮料', '家居用品', '美妆个护']
values = [420, 380, 290, 350, 210]
plt.barh(categories, values, color='lightcoral')
plt.title('水平柱状图(条形图)')
plt.xlabel('销售额 (万元)')
plt.tight_layout()
plt.show()
import numpy as np
import matplotlib.pyplot as plt
# 数据
categories = ['2019', '2020', '2021', '2022']
exp_A = [22, 28, 35, 42] # 实验组A
exp_B = [20, 26, 33, 40] # 实验组B
ctrl = [18, 22, 28, 35] # 对照组
errors_A = [1.5, 2, 2.5, 3]
errors_B = [1.2, 1.8, 2.2, 2.8]
errors_ctrl = [1, 1.5, 2, 2.5]
x = np.arange(len(categories))
width = 0.25
fig, ax = plt.subplots(figsize=(10, 6))
bars_A = ax.bar(x - width, exp_A, width, yerr=errors_A, capsize=3,
label='实验组A', color='#1f77b4', edgecolor='black')
bars_B = ax.bar(x, exp_B, width, yerr=errors_B, capsize=3,
label='实验组B', color='#ff7f0e', edgecolor='black')
bars_ctrl = ax.bar(x + width, ctrl, width, yerr=errors_ctrl, capsize=3,
label='对照组', color='#2ca02c', edgecolor='black')
# 添加数据标签
for bars in [bars_A, bars_B, bars_ctrl]:
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height + 1,
f'{height}', ha='center', va='bottom', fontsize=9)
ax.set_xlabel('年份')
ax.set_ylabel('观测值')
ax.set_title('分组柱状图 - 实验数据对比 (含误差线)')
ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend()
plt.tight_layout()
plt.show()
使用 savefig() 保存为常见格式:
plt.savefig('bar_chart.png', dpi=300, bbox_inches='tight') # 高清PNG
plt.savefig('bar_chart.pdf', bbox_inches='tight') # 矢量PDF
柱状图是展示分类数据对比的核心工具,掌握分组、堆叠、标签和误差线的用法,能让你的数据故事更加清晰有力。下一章我们将学习直方图,用于展示连续数据的分布。