Skip to content

Matplotlib 柱状图:plt.bar() 和 plt.barh() 完全指南

Updated on

柱状图是跨类别比较数量的最常用方式。按季度的收入、按学生的分数、按状态的计数——柱状图使这些比较一目了然。但在 Matplotlib 中创建有效的柱状图需要的不仅仅是简单的 plt.bar() 调用。你需要处理分组比较、堆叠组合、长标签的水平布局,以及使图表自明的适当注释。

本指南涵盖了在 Matplotlib 中你需要的每种柱状图模式,从基本的垂直柱到高级的分组和堆叠配置。

📚

基本垂直柱状图

import matplotlib.pyplot as plt
 
categories = ['Python', 'JavaScript', 'Java', 'C++', 'Go']
values = [35, 28, 22, 15, 12]
 
plt.figure(figsize=(8, 5))
plt.bar(categories, values, color='steelblue', edgecolor='black', linewidth=0.5)
plt.xlabel('语言')
plt.ylabel('流行度评分')
plt.title('编程语言流行度')
plt.show()

使用 plt.barh() 创建水平柱状图

当类别标签较长或有很多类别时使用水平柱:

import matplotlib.pyplot as plt
 
frameworks = ['React', 'Vue.js', 'Angular', 'Svelte', 'Next.js',
              'Django', 'Flask', 'FastAPI', 'Express', 'Rails']
stars = [220, 207, 95, 78, 124, 78, 67, 74, 64, 55]
 
plt.figure(figsize=(10, 6))
plt.barh(frameworks, stars, color='#3498db', edgecolor='white')
plt.xlabel('GitHub Stars(千)')
plt.title('按 GitHub Stars 排列的框架流行度')
plt.gca().invert_yaxis()  # 最高的在顶部
plt.tight_layout()
plt.show()

自定义颜色

import matplotlib.pyplot as plt
 
categories = ['Q1', 'Q2', 'Q3', 'Q4']
revenue = [120, 150, 180, 200]
 
# 每个柱不同颜色
colors = ['#e74c3c', '#f39c12', '#2ecc71', '#3498db']
 
plt.figure(figsize=(8, 5))
bars = plt.bar(categories, revenue, color=colors, edgecolor='black', linewidth=0.5)
plt.ylabel('收入($K)')
plt.title('季度收入')
plt.show()

在柱上添加数值标签

import matplotlib.pyplot as plt
 
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]
 
plt.figure(figsize=(8, 5))
bars = plt.bar(categories, values, color='steelblue')
 
# 在每个柱顶部添加数值标签
for bar, val in zip(bars, values):
    plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 1,
             str(val), ha='center', va='bottom', fontsize=11)
 
plt.ylabel('值')
plt.title('带数值标签的柱状图')
plt.show()

分组柱状图

并排比较多个系列:

import matplotlib.pyplot as plt
import numpy as np
 
categories = ['Q1', 'Q2', 'Q3', 'Q4']
product_a = [20, 35, 30, 35]
product_b = [25, 32, 34, 20]
product_c = [15, 20, 25, 30]
 
x = np.arange(len(categories))
width = 0.25
 
plt.figure(figsize=(10, 6))
plt.bar(x - width, product_a, width, label='产品 A', color='#e74c3c')
plt.bar(x, product_b, width, label='产品 B', color='#3498db')
plt.bar(x + width, product_c, width, label='产品 C', color='#2ecc71')
 
plt.xlabel('季度')
plt.ylabel('销售额($K)')
plt.title('按产品分类的季度销售额')
plt.xticks(x, categories)
plt.legend()
plt.tight_layout()
plt.show()

堆叠柱状图

显示每个类别的构成:

import matplotlib.pyplot as plt
 
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
mobile = [30, 35, 40, 45]
desktop = [50, 45, 35, 30]
tablet = [20, 20, 25, 25]
 
plt.figure(figsize=(8, 6))
plt.bar(quarters, mobile, label='移动端', color='#3498db')
plt.bar(quarters, desktop, bottom=mobile, label='桌面端', color='#e74c3c')
 
# 第三层堆叠需要计算累积底部
import numpy as np
bottom_2 = np.array(mobile) + np.array(desktop)
plt.bar(quarters, tablet, bottom=bottom_2, label='平板', color='#2ecc71')
 
plt.ylabel('流量(%)')
plt.title('按季度的流量来源')
plt.legend()
plt.show()

误差线

import matplotlib.pyplot as plt
import numpy as np
 
categories = ['对照组', '处理 A', '处理 B', '处理 C']
means = [10.2, 15.8, 14.3, 18.1]
errors = [1.2, 2.1, 1.8, 2.5]
 
plt.figure(figsize=(8, 5))
plt.bar(categories, means, yerr=errors, capsize=5,
        color='steelblue', edgecolor='black', linewidth=0.5)
plt.ylabel('响应值')
plt.title('带误差线的处理效果')
plt.show()

plt.bar() 参数参考

参数类型描述
x类数组柱的位置(类别)
height类数组柱的高度(值)
widthfloat柱宽(默认 0.8)
bottom类数组柱底部的 Y 坐标(用于堆叠)
color颜色或数组柱的填充颜色
edgecolor颜色柱的边框颜色
linewidthfloat边框线宽
yerr / xerr类数组误差线大小
capsizefloat误差线帽宽度
alignstr柱的对齐方式('center' 或 'edge')
labelstr图例标签
alphafloat透明度(0-1)

使用 PyGWalker 创建交互式柱状图

对于探索性数据分析,PyGWalker (opens in a new tab) 让你在 Jupyter 中通过拖放 DataFrame 的列来创建交互式柱状图:

import pandas as pd
import pygwalker as pyg
 
df = pd.DataFrame({
    'Quarter': ['Q1', 'Q2', 'Q3', 'Q4'] * 3,
    'Product': ['A'] * 4 + ['B'] * 4 + ['C'] * 4,
    'Sales': [20, 35, 30, 35, 25, 32, 34, 20, 15, 20, 25, 30]
})
 
walker = pyg.walk(df)

FAQ

如何在 Matplotlib 中创建柱状图?

使用 plt.bar(类别, 值) 创建垂直柱或 plt.barh(类别, 值) 创建水平柱。传递类别及其对应值的列表或数组。添加 plt.xlabel()plt.ylabel()plt.title() 作为标签。

如何创建分组柱状图?

使用 np.arange() 设置 x 位置,每组按柱宽偏移。多次调用 plt.bar() 并使用偏移的 x 位置:plt.bar(x - width, data1, width)plt.bar(x, data2, width) 等。用 plt.xticks(x, 类别) 设置刻度标签。

如何在柱顶添加数值标签?

遍历柱对象并使用 plt.text()。对每个柱,用 bar.get_x() + bar.get_width() / 2 计算中心 x 位置,用 bar.get_height() 计算 y 位置。使用 ha='center' 进行水平居中。

如何创建堆叠柱状图?

在连续的 plt.bar() 调用中使用 bottom 参数。第一次调用没有 bottom。第二次调用使用第一个数据集作为 bottom。第三层堆叠将前两个数据集求和作为 bottom

什么时候应该使用水平柱还是垂直柱?

当类别标签较长、类别较多(超过 8-10 个)或与基线比较时使用水平柱(plt.barh())。对于时间序列类别(月、季度)或标签较短的少量类别使用垂直柱(plt.bar())。

总结

Matplotlib 的 plt.bar()plt.barh() 满足了所有柱状图需求:基本比较、分组多系列、堆叠组合和带注释的展示。对于分组柱,使用 np.arange() 偏移 x 位置。对于堆叠柱,使用 bottom 参数。始终添加数值标签以提高清晰度,当标签较长时选择水平布局。

📚