☰
Matplotlib柱状图全解析:从基础到高级应用
2026/10/15 10:57:55 网站建设 项目流程

1. 为什么我们需要掌握Matplotlib柱状图?

柱状图是数据可视化中最基础也最常用的图表类型之一。作为Python生态中最主流的绘图库,Matplotlib提供了极其灵活的柱状图绘制能力。但在实际工作中,我发现很多数据分析师只会用最简单的plt.bar(),遇到稍微复杂的需求就束手无策。

今天我就结合自己5年多的数据可视化经验,带大家彻底掌握Matplotlib柱状图的四大核心类型:垂直柱状图、水平柱状图、分组柱状图和堆叠柱状图。每种类型我都会给出典型应用场景、完整代码示例和关键参数解析,让你能够应对90%以上的业务对比需求。

2. 垂直柱状图:最基础的对比方式

2.1 基础垂直柱状图实现

垂直柱状图是默认的柱状图形式,适合展示不同类别间的数值对比。假设我们要比较某电商平台5个品类的月销售额:

import matplotlib.pyplot as plt import numpy as np categories = ['服饰', '数码', '家居', '美妆', '食品'] sales = [125, 89, 72, 103, 56] plt.bar(categories, sales) plt.title('各品类月销售额对比') plt.ylabel('销售额(万元)') plt.show()

这里有几个关键点需要注意:

  • 第一个参数是x轴类别标签
  • 第二个参数是对应的高度值
  • 默认柱体宽度为0.8,颜色为蓝色

2.2 高级定制技巧

实际项目中我们通常需要更精细的控制:

plt.bar(categories, sales, width=0.6, # 控制柱体宽度 color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8'], # 自定义颜色 edgecolor='black', # 边框颜色 linewidth=1.2) # 边框粗细 # 添加数据标签 for i, v in enumerate(sales): plt.text(i, v+2, str(v), ha='center') plt.xticks(rotation=30) # x轴标签旋转 plt.grid(axis='y', linestyle='--', alpha=0.7) # 只显示y轴网格线

提示:当类别较多时,适当减小width值(0.4-0.6)可以避免柱体重叠,同时旋转x轴标签(rotation=30/45)能提升可读性。

3. 水平柱状图:长类别名称的最佳选择

3.1 基础水平柱状图

当我们的类别名称较长,或者想强调排名时,水平柱状图是更好的选择。使用plt.barh()即可实现:

products = ['超薄笔记本电脑2023款', '智能扫地机器人Pro', '无线降噪耳机旗舰版', '4K超清智能电视'] sales_volume = [320, 450, 280, 390] plt.barh(products, sales_volume, height=0.5) # height相当于垂直图的width plt.title('热门商品销量对比') plt.xlabel('销量(千台)') plt.show()

3.2 排序与标签优化

为了让数据更直观,我们通常需要对数据进行排序:

# 将数据和标签一起排序 sorted_data = sorted(zip(sales_volume, products), reverse=True) sales_sorted, products_sorted = zip(*sorted_data) plt.barh(products_sorted, sales_sorted, color='#6A8CAF') plt.xlim(0, 500) # 固定x轴范围 # 在柱体内部显示数值 for index, value in enumerate(sales_sorted): plt.text(value-30, index, str(value), va='center', color='white', fontweight='bold')

注意:水平柱状图的y轴是从下往上增长的,所以index=0对应最下方的柱体。这与垂直柱状图的x轴从左到右增长是一致的。

4. 分组柱状图:多维度对比利器

4.1 基础分组柱状图

当我们需要同时对比多个系列在不同类别下的表现时,分组柱状图就派上用场了。比如比较Q1和Q2各品类的销售情况:

import numpy as np categories = ['服饰', '数码', '家居', '美妆'] q1_sales = [120, 85, 70, 95] q2_sales = [135, 92, 68, 110] x = np.arange(len(categories)) # 类别位置 width = 0.35 # 柱体宽度 plt.bar(x - width/2, q1_sales, width, label='Q1') plt.bar(x + width/2, q2_sales, width, label='Q2') plt.xticks(x, categories) plt.legend() plt.title('各品类Q1 vs Q2销售额对比') plt.ylabel('销售额(万元)')

4.2 复杂分组场景

对于更复杂的分组场景(如三个季度的对比),我们需要调整布局:

q3_sales = [128, 100, 75, 120] width = 0.25 plt.bar(x - width, q1_sales, width, label='Q1') plt.bar(x, q2_sales, width, label='Q2') plt.bar(x + width, q3_sales, width, label='Q3') # 添加数据标签 def add_labels(bars): for bar in bars: height = bar.get_height() plt.text(bar.get_x() + bar.get_width()/2., height, f'{height:.0f}', ha='center', va='bottom') add_labels(plt.gca().containers[0]) add_labels(plt.gca().containers[1]) add_labels(plt.gca().containers[2])

经验:当分组超过3个时,考虑使用堆叠柱状图或分面图(subplots),避免图表过于拥挤。

5. 堆叠柱状图:展示部分与整体关系

5.1 基础堆叠柱状图

堆叠柱状图适合展示各类别的构成情况。比如展示各品类中不同价格段产品的销售占比:

low_price = [30, 25, 20, 35] mid_price = [50, 40, 30, 45] high_price = [40, 20, 20, 30] plt.bar(categories, low_price, label='低价位') plt.bar(categories, mid_price, bottom=low_price, label='中价位') plt.bar(categories, high_price, bottom=np.array(low_price)+np.array(mid_price), label='高价位') plt.legend() plt.title('各品类不同价位产品销售额构成') plt.ylabel('销售额(万元)')

5.2 百分比堆叠柱状图

有时我们更关心比例而非绝对值:

# 计算各品类总和 total = np.array(low_price) + np.array(mid_price) + np.array(high_price) # 转换为百分比 low_pct = low_price / total * 100 mid_pct = mid_price / total * 100 high_pct = high_price / total * 100 plt.bar(categories, low_pct, label='低价位') plt.bar(categories, mid_pct, bottom=low_pct, label='中价位') plt.bar(categories, high_pct, bottom=low_pct+mid_pct, label='高价位') plt.legend(loc='upper right', bbox_to_anchor=(1.15, 1)) plt.ylabel('占比(%)') plt.title('各品类不同价位产品销售额占比')

提示:使用np.array进行向量运算可以避免显式循环,代码更简洁高效。bbox_to_anchor参数可以将图例移到图表外部,避免遮挡数据。

6. 常见问题与解决方案

6.1 柱体重叠或间距不当

这是新手最常见的问题之一。解决方案:

  • 调整width/height参数(0.4-0.8之间)
  • 对于分组柱状图,确保x轴位置计算正确
  • 使用plt.tight_layout()自动调整布局

6.2 数据标签显示不全

当数值差异较大时,部分标签可能超出图表范围:

plt.ylim(0, max(sales)*1.2) # 留出20%空间给标签

或者将标签显示在柱体内部:

plt.text(x, height/2, label, ha='center', va='center', color='white')

6.3 图例遮挡数据

三种解决方案:

  1. 调整图例位置:plt.legend(loc='upper right')
  2. 将图例移到图表外部:bbox_to_anchor=(1.05, 1)
  3. 使用plt.tight_layout()自动调整

6.4 性能优化技巧

当数据量较大时(>1000个柱体):

  • 使用plt.bar的bottom参数替代多次调用plt.bar
  • 关闭抗锯齿:plt.rcParams['path.simplify'] = True
  • 减少刻度数量:plt.locator_params(axis='x', nbins=10)

7. 高级应用与扩展

7.1 误差棒柱状图

在科研领域,经常需要显示误差范围:

means = [20, 35, 30, 25] stds = [2, 3, 4, 1] plt.bar(categories, means, yerr=stds, capsize=5) plt.ylabel('测量值') plt.title('带误差棒的柱状图')

7.2 渐变颜色柱状图

使用颜色映射增强可视化效果:

from matplotlib.cm import ScalarMappable norm = plt.Normalize(min(sales), max(sales)) colors = plt.cm.viridis(norm(sales)) plt.bar(categories, sales, color=colors) plt.colorbar(ScalarMappable(norm=norm, cmap='viridis'), label='销售额强度')

7.3 交互式柱状图

结合mplcursors库实现悬停提示:

import mplcursors bars = plt.bar(categories, sales) cursor = mplcursors.cursor(bars, hover=True) @cursor.connect("add") def on_add(sel): sel.annotation.set_text(f'{sel.artist.get_label()}: {sel.target[1]:.0f}万')

在实际项目中,我通常会根据具体需求混合使用这些技巧。比如一个电商数据分析报告可能包含:

  • 垂直柱状图展示各品类销售对比
  • 分组柱状图比较不同季度表现
  • 堆叠柱状图分析各品类用户年龄构成
  • 水平柱状图展示热销商品排名

掌握这些柱状图变体后,你就能应对绝大多数业务场景的数据可视化需求了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询