Python图表叠加柱状图折线图组合图:双轴混合图表
用Python matplotlib在一张图上叠加柱状图和折线图,双Y轴展示量级不同的两个指标,代码完整可运行,适合销售业绩和增长率组合分析。
场景痛点
做经营分析时,一张图上想同时看"月度销售额(柱)"和"利润率(线)",销售额几十万、利润率百分之几,两个指标量级差100倍,硬放一个轴折线就贴底了。Excel做组合图要右键"更改系列图表类型"再选次坐标轴,操作绕。matplotlib用 twinx() 几行代码就能把柱子和折线叠在一张图上,左轴柱、右轴线,一目了然。
用到的库
pip install matplotlib
完整代码
# 导入库
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
# 解决中文乱码
matplotlib.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei", "Arial Unicode MS"]
matplotlib.rcParams["axes.unicode_minus"] = False
def draw_combo_chart():
months = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月"]
sales = [120, 150, 180, 160, 210, 260, 240, 290] # 销售额(万元)
profit_rate = [0.18, 0.20, 0.22, 0.19, 0.24, 0.26, 0.25, 0.28] # 利润率
fig, ax1 = plt.subplots(figsize=(10, 6))
# ===== 左轴:柱状图 销售额 =====
bar_color = "#4C72B0"
bars = ax1.bar(months, sales, color=bar_color, alpha=0.7, width=0.5, label="销售额")
ax1.set_xlabel("月份", fontsize=12)
ax1.set_ylabel("销售额(万元)", fontsize=12, color=bar_color)
ax1.tick_params(axis="y", labelcolor=bar_color)
ax1.set_ylim(0, 360)
# 柱顶标注销售额
for bar in bars:
h = bar.get_height()
ax1.text(bar.get_x() + bar.get_width() / 2, h + 5,
f"{h}", ha="center", fontsize=9, color=bar_color)
# ===== 右轴:折线 利润率 =====
ax2 = ax1.twinx()
line_color = "#C44E52"
ax2.plot(months, profit_rate, color=line_color, marker="o",
linewidth=2.5, markersize=8, label="利润率")
ax2.set_ylabel("利润率", fontsize=12, color=line_color)
ax2.tick_params(axis="y", labelcolor=line_color)
ax2.set_ylim(0, 0.4)
# 右轴格式化成百分比
ax2.yaxis.set_major_formatter(plt.FuncFormatter(lambda v, _: f"{v:.0%}"))
# 折线点上方标注利润率
for i, rate in enumerate(profit_rate):
ax2.text(i, rate + 0.015, f"{rate:.0%}", ha="center",
fontsize=9, color=line_color)
# 合并两个轴的图例
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax1.legend(h1 + h2, l1 + l2, loc="upper left")
plt.title("月度销售额与利润率组合图", fontsize=16)
plt.tight_layout()
plt.savefig("combo_bar_line.png", dpi=150)
plt.close()
print("组合图已保存为 combo_bar_line.png")
if __name__ == "__main__":
draw_combo_chart()
代码讲解
ax1.bar()在左轴画蓝色半透明柱子表示销售额,alpha=0.7让柱子不要太抢戏,折线叠在上面更突出。ax2 = ax1.twinx()创建共享X轴的右轴,ax2.plot()画红色折线表示利润率,marker="o"在每个月数据点画圆点。- 两个轴的刻度颜色分别和柱子、折线对应,
tick_params(labelcolor=...)让读图时不会搞混哪根线对应哪个轴。 - 左右轴的范围手动设置:左轴
0~360,右轴0~0.4,这样柱子和折线不会挤在同一条水平线上,视觉层次清晰。 FuncFormatter把右轴小数转成百分比格式,0.25 显示成 25%。- 柱顶和折线上都加了数值标签,读者不用对照轴就能读到精确数字。
- 图例用
get_legend_handles_labels()把两个轴的图例句柄合并,放左上角。
运行结果
当前目录生成 combo_bar_line.png,图中蓝色柱子是月度销售额(左轴),红色带圆点折线是利润率(右轴,百分比格式),柱顶和折线点上方都标注了具体数值。整体能看出销售额在波动上升,利润率也稳步走高。
注意事项
- 组合图最容易犯的错是两个轴起点不从0开始,导致视觉对比失真。柱图必须从0起,折线可以从合理值起,但报告里要注明。
- 柱子宽度
width=0.5比较舒服,太宽会显得笨重,太窄会和折线混淆。 - 右轴百分比范围根据实际数据调,如果利润率在10%~30%之间,
set_ylim(0, 0.4)合适;如果是个位数,改成0~0.15。 - pyecharts也能做组合图,用
Bar().overlap(Line()),需要交互式版本时可以参考。

更新时间:2026-09-14 20:33:08
上一篇:Python根据Excel数据画趋势图:pandas读取matplotlib出图