Matplotlib 柱形图

Matplotlib 柱形图(Bar)完全指南

柱形图是 数据对比、排名、分布展示 的王牌工具。本教程带你从入门到 发表级,掌握 垂直/水平柱状图、堆叠、分组、误差棒、动态标注、瀑布图、双向图、艺术风格 等全部技巧。


一、基本柱形图

import matplotlib.pyplot as plt
import numpy as np

categories = ['A', 'B', 'C', 'D', 'E']
values = [3, 7, 2, 5, 8]

plt.bar(categories, values)
plt.show()

二、核心参数详解

plt.bar(categories, values,
        width=0.8,           # 柱宽
        color='skyblue',     # 颜色
        edgecolor='black',   # 边框
        linewidth=1.2,       # 边框宽度
        alpha=0.9,           # 透明度
        label='数据')         # 图例

三、水平柱形图 barh

plt.barh(categories, values, 
         height=0.7, 
         color='lightcoral', 
         edgecolor='darkred')
plt.xlabel('值')
plt.ylabel('类别')
plt.show()

四、颜色设置

1. 统一颜色

plt.bar(categories, values, color='steelblue')

2. 每柱不同颜色

colors = ['red', 'orange', 'yellow', 'green', 'blue']
plt.bar(categories, values, color=colors)

3. 渐变色(推荐)

from matplotlib.cm import get_cmap
cmap = get_cmap('viridis')
colors = cmap(np.linspace(0, 1, len(values)))
plt.bar(categories, values, color=colors)

五、堆叠柱形图(Stacked Bar)

group1 = [3, 7, 2, 5]
group2 = [2, 4, 3, 1]
group3 = [1, 2, 4, 3]

plt.bar(categories, group1, label='组1')
plt.bar(categories, group2, bottom=group1, label='组2')
plt.bar(categories, group3, bottom=np.array(group1)+np.array(group2), label='组3')

plt.legend()
plt.show()

bottom= 控制堆叠起始高度


六、分组柱形图(Grouped Bar)

x = np.arange(len(categories))
width = 0.25

plt.bar(x - width, group1, width, label='组1', color='skyblue')
plt.bar(x,        group2, width, label='组2', color='lightcoral')
plt.bar(x + width, group3, width, label='组3', color='lightgreen')

plt.xticks(x, categories)
plt.legend()
plt.show()

七、误差棒(Error Bars)

errors = [0.5, 0.8, 0.3, 0.6, 1.0]

plt.bar(categories, values, 
        yerr=errors, 
        capsize=5,           # 误差棒端点小横线
        error_kw={'elinewidth': 2, 'capthick': 2},
        color='lightblue', edgecolor='navy')
plt.show()

八、自动标注数值

bars = plt.bar(categories, values, color='steelblue', edgecolor='black')

for bar in bars:
    height = bar.get_height()
    plt.text(bar.get_x() + bar.get_width()/2, height + 0.1,
             f'{height}', 
             ha='center', va='bottom', fontsize=10, fontweight='bold')

plt.ylim(0, max(values) * 1.15)
plt.show()

九、双向柱形图(人口金字塔)

ages = ['0-10', '11-20', '21-30', '31-40', '41-50']
male = [12, 15, 18, 14, 10]
female = [11, 16, 19, 13, 9]

y = np.arange(len(ages))

plt.barh(y, [-m for m in male], height=0.8, label='男性', color='skyblue')
plt.barh(y, female, height=0.8, label='女性', color='lightpink')

plt.yticks(y, ages)
plt.xlabel('人口数量 (万人)')
plt.legend()
plt.title('人口金字塔')
plt.show()

十、瀑布图(Waterfall)

steps = ['初始', '+收入', '-成本', '+投资', '-税费', '=总计']
values = [100, 50, -30, 20, -15, 0]  # 最后一项为0

colors = ['gray'] + ['green' if v > 0 else 'red' for v in values[1:-1]] + ['blue']

# 计算累计
cumsum = np.cumsum([0] + values[:-1])
bottom = cumsum
height = values[:-1] + [cumsum[-1]]

plt.bar(steps, height, bottom=bottom, color=colors, edgecolor='black')
plt.axhline(0, color='black', linewidth=0.8)
plt.title('瀑布图:利润分解')
plt.show()

十一、完整专业示例(论文级)

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('seaborn-v0_8')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 数据
cities = ['北京', '上海', '广州', '深圳', '杭州', '成都']
sales_2023 = [85, 92, 78, 88, 75, 70]
sales_2024 = [90, 88, 82, 95, 80, 76]
errors = [3, 4, 2, 5, 3, 4]

x = np.arange(len(cities))
width = 0.35

fig, ax = plt.subplots(figsize=(12, 8))

# 分组柱状图
bars1 = ax.bar(x - width/2, sales_2023, width, 
               label='2023年', color='#1f77b4', edgecolor='navy', linewidth=1.2,
               yerr=errors, capsize=6, error_kw={'elinewidth':2, 'capthick':2})

bars2 = ax.bar(x + width/2, sales_2024, width, 
               label='2024年', color='#ff7f0e', edgecolor='darkred', linewidth=1.2,
               yerr=errors, capsize=6, error_kw={'elinewidth':2, 'capthick':2})

# 标注数值
def autolabel(bars):
    for bar in bars:
        height = bar.get_height()
        ax.text(bar.get_x() + bar.get_width()/2, height + 3,
                f'{int(height)}', ha='center', va='bottom', fontsize=10, fontweight='bold')

autolabel(bars1)
autolabel(bars2)

# 美化
ax.set_xlabel('城市', fontsize=14, fontweight='bold')
ax.set_ylabel('销售额 (亿元)', fontsize=14, fontweight='bold')
ax.set_title('2023-2024年城市销售额对比分析', fontsize=18, fontweight='bold', pad=20)
ax.set_xticks(x)
ax.set_xticklabels(cities, fontsize=12)
ax.set_ylim(0, 110)

ax.legend(fontsize=12, frameon=True, fancybox=True, shadow=True)
ax.grid(True, axis='y', alpha=0.3, linestyle='--', linewidth=0.8)
ax.set_facecolor('#f8f9fa')

# 边框优化
for spine in ax.spines.values():
    spine.set_linewidth(1.2)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.tight_layout()
plt.savefig('bar_pro.png', dpi=300, bbox_inches='tight', facecolor='white')
plt.show()

十二、柱形图速查表(收藏用)

# 基础
plt.bar(categories, values)

# 水平
plt.barh(categories, values)

# 堆叠
plt.bar(x, v1)
plt.bar(x, v2, bottom=v1)

# 分组
plt.bar(x-width, v1, width)
plt.bar(x+width, v2, width)

# 误差棒
plt.bar(..., yerr=errors, capsize=5)

# 标注
for bar in bars:
    plt.text(bar.get_x()+bar.get_width()/2, bar.get_height(), f'{bar.get_height()}')

# 颜色渐变
colors = plt.cm.viridis(np.linspace(0,1,len(values)))

十三、常见问题解决

问题解决方案
柱子太挤减小 width,增大 figsize
标签重叠plt.xticks(rotation=45)
数值被截断plt.ylim(0, max*1.15)
颜色单调使用 cmap 渐变
保存裁剪plt.savefig(..., bbox_inches='tight')

十四、推荐风格模板

场景推荐设置
论文蓝橙配色,误差棒,数值标注
PPT粗柱,醒目颜色,alpha=0.9
仪表盘水平柱,渐变色
排名图降序排序,color='gold' 冠军

官方文档

  • Bar API:https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar.html
  • 示例图库:https://matplotlib.org/stable/gallery/statistics/index.html#bars-and-error-bars

总结:三步打造专业柱形图

# 1. 数据 + 布局
x = np.arange(len(cats))
bars = plt.bar(x, values, width=0.6, color=colors, edgecolor='black')

# 2. 标注 + 误差
for bar in bars: plt.text(...)
plt.bar(..., yerr=errors, capsize=5)

# 3. 美化输出
plt.title('标题', fontsize=16, pad=20)
plt.tight_layout()
plt.savefig('fig.png', dpi=300, bbox_inches='tight')

一键生成分组柱状图

x = np.arange(5)
plt.bar(x-0.2, [3,7,2,5,8], 0.4, label='2023', color='skyblue')
plt.bar(x+0.2, [4,6,3,6,7], 0.4, label='2024', color='lightcoral')
plt.xticks(x, ['A','B','C','D','E'])
plt.legend()
plt.show()

需要我为你:

  • 生成 10种经典柱形图模板
  • 制作 Jupyter 柱形图交互小工具(滑块切换年份)?
  • 输出 LaTeX/PPT 可用代码

告诉我你的需求!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部