目录

一、pyplot

1. 什么是状态机接口

2. pyplot 典型代码示例

3. pyplot 接口的优势与局限性

二、常见图

1. 折线图

2. 柱状图

3. 饼图

4. 散点图

5. 箱线图

三、面向对象接口

1. Figure 与 Axes

2. plt.subplots()

3. 为什么推荐面向对象接口

4. 代码案例

四、图形美化

1. 画布尺寸设置

2. 标题与坐标轴标签(title / xlabel / ylabel)

3. 图例配置(legend)

4. 网格辅助线(grid)

总结


一、pyplot

在 Matplotlib 的体系中,matplotlib.pyplot(通常简写为 plt)是最先接触到的模块。它提供了一套类似于 MATLAB 风格的状态机接口,旨在让用户能以极简的代码量完成数据的图形化展示


1. 什么是状态机接口

所谓状态接口,是指 pyplot 在后台隐式维护着一个全局状态。当你调用 pyplot 的各个函数时,系统会自动跟踪并锁定当前的画布与当前的坐标系

这种设计模式的核心特点是隐式操作

  • 调用 plt.figure() 时,后台会自动创建并激活一个新的画布

  • 调用 plt.plot() 时,图形会自动绘制在当前处于激活状态的坐标系上

  • 调用 plt.title() 或 plt.xlabel() 时,相关文本标注会直接叠加到当前坐标系中

在此模式下,开发者无需显式地创建图表变量,也不需要将对象作为参数传递,所有绘图指令均按照代码的顺序依次叠加生效


2. pyplot 典型代码示例

以下是一个基于 pyplot 接口绘制基础折线图的典型代码示例:

import matplotlib.pyplot as plt

# 1. 准备数据
x = [1, 2, 3, 4, 5]
y = [2, 5, 7, 8, 11]

# 2. 创建画布与绘制图形(隐式作用于当前全局状态)
plt.figure(figsize=(8, 4))
plt.plot(x, y, color='steelblue', linestyle='--', marker='o')

# 3. 添加图表元数据
plt.title('Monthly Sales Growth Trend')
plt.xlabel('Month')
plt.ylabel('Sales (k USD)')
plt.grid(True)

# 4. 渲染图表
plt.show()

输出结果:

在这个流程中,所有的 plt. 方法都直接作用于全局状态下的图表,逻辑顺畅,阅读门槛低


3. pyplot 接口的优势与局限性

优势

  • 代码简洁:省去了对象实例化与引用的代码,适合快速上手

  • 适配探索性分析:在 Jupyter Notebook 中进行即时的数据预览或快速验证假设时,能够提供极高的交互效率

局限性

  • 状态混淆风险:当脚本中同时存在多个画布或涉及复杂的多子图交替绘制时,仅依赖隐式状态容易导致绘图指令作用错位

  • 定制粒度受限:对于复杂的嵌套排版、多轴联动或极深度的细微样式调整,pyplot 的表达能力相对受限

pyplot 接口是 Matplotlib 提供的 "快捷通道",它通过封装底层的对象逻辑,为日常分析提供了直观高效的工具。理解其状态机的运作机制,不仅有助于高效进行基础绘图,也为后续过渡到面向对象接口打下逻辑基础

二、常见图

在实际分析工作中,熟练掌握常用图表的 API 接口签名及其核心参数,是提高绘图效率的关键。本章将详细介绍五种最基础且常用的图表类型,并给出对应的 API 方法签名、核心参数说明及完整代码示例


1. 折线图

折线图主要用于展示数据随连续变量(通常是时间)的变化趋势

plt.plot(x, y, fmt=None, *, lineStyle=None, lineWidth=None, 
         color=None, marker=None, label=None, **kwargs)

x, y:数据点的横轴与纵轴坐标
fmt:快捷格式化字符串,如 'r--o' 代表红色(r)、虚线(--)、圆点标记(o)
color:指定线条颜色,支持颜色名称(如 'blue')、HEX 码
linestyle:线条样式,常用取值有 '-'(实线)、'--'(虚线)、'-.'(点划线)、':'(点线)
linewidth:线条宽度,数值型(如 2.0)
marker:数据点标记形状,如 'o'(圆点)、's'(方块)、'^'(三角形)
label:数据序列的标签,用于生成图例

代码示例

# 准备数据
months = [1, 2, 3, 4, 5, 6]
sales = [120, 135, 125, 145, 160, 175]

# 绘制折线图
plt.figure(figsize=(7, 4))
plt.plot(months, sales, color='#2b5c8f', 
         linestyle='-', linewidth=2, marker='o', label='Product A')

plt.title('Monthly Sales Trend')
plt.xlabel('Month')
plt.ylabel('Sales Volume')
plt.legend()
plt.grid(True, linestyle=':', alpha=0.6)
plt.show()

输出结果:


2. 柱状图

柱状图用于比较离散分类数据之间的数值大小差异

plt.bar(x, height, width=0.8, bottom=None, *, align='center', 
        color=None, edgecolor=None, label=None, **kwargs)

x:分类标签的横坐标
height:柱体的高度(对应数值大小)
width:柱体的宽度
bottom:柱体基底的 Y 轴坐标
align:柱体与 X 轴刻度的对齐方式,可选 'center'(居中)或 'edge'(对齐边沿)
color:柱体的填充颜色
edgecolor:柱体边框线颜色

若需绘制水平条形图,可使用 plt.barh(y, width, height=0.8, left=None, ...) 接口

代码示例

# 准备数据
categories = ['East', 'West', 'South', 'North']
revenue = [450, 320, 280, 410]

# 绘制柱状图
plt.figure(figsize=(7, 4))
plt.bar(categories, revenue, width=0.5, color='#4c8be2', 
        edgecolor='#1d4e89', label='Revenue')

plt.title('Regional Revenue Comparison')
plt.xlabel('Region')
plt.ylabel('Revenue (k USD)')
plt.legend()
plt.show()

输出结果:


3. 饼图

饼图用于呈现离散分类占总体的比例关系

plt.pie(x, explode=None, labels=None, colors=None, 
        autopct=None, shadow=False, startangle=0, **kwargs)

x:各部分的数值序列
labels:各扇区的分类文本标签
autopct:控制扇区内百分比数字的格式化字符串
explode:指定各扇区偏离中心的距离列表(例如 [0, 0.1, 0] 用于突出显示第二个扇区)
colors:各个扇区的颜色列表
startangle:饼图绘制的起始角度,默认为 0(从 X 轴正方向逆时针旋转)

代码示例

market_share = [35, 25, 20, 20]
labels = ['Brand A', 'Brand B', 'Brand C', 'Others']
explode = [0.05, 0, 0, 0]  # 突出显示第一项

# 绘制饼图
plt.figure(figsize=(6, 6))
plt.pie(
    market_share, 
    labels=labels, 
    autopct='%.1f%%', 
    explode=explode, 
    startangle=140,
    colors=['#5b9bd5', '#ed7d31', '#a5a5a5', '#ffc000']
)

plt.title('Market Share Distribution')
plt.show()

输出结果:


4. 散点图

散点图用于探索两个连续变量之间的分布模式、相关性或异类聚集情况

plt.scatter(x, y, s=None, c=None, marker=None, 
            cmap=None, alpha=None, label=None, **kwargs)

x, y:数据点的二元坐标序列
s:散点的大小
c:散点的颜色
marker:散点的形状符号
cmap:色彩映射表,当 c 为连续数值时生效
alpha:透明度(0.0 全透明至 1.0 不透明)

代码示例

ad_budget = [10, 20, 30, 40, 50, 60, 70, 80]
sales_volume = [15, 28, 36, 45, 51, 68, 74, 89]
conversions = [100, 200, 350, 400, 500, 750, 800, 950]  # 映射为点的大小

# 绘制散点图
plt.figure(figsize=(7, 4))
plt.scatter(ad_budget, sales_volume, s=conversions, 
            c=sales_volume, cmap='Blues', alpha=0.8, edgecolors='black')

plt.title('Ad Budget vs. Sales Volume')
plt.xlabel('Ad Budget (k USD)')
plt.ylabel('Sales Volume (k Units)')
plt.colorbar(label='Sales Scale')
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()

输出结果:


5. 箱线图

箱线图主要用于展示数据的五数概括(最小值、下四分位数、中位数、上四分位数、最大值)以及统计异常值

plt.boxplot(x, notch=None, vert=None, patch_artist=None, 
            labels=None, showmeans=None, **kwargs)

x:输入数据,可以是单个序列,也可以是二维数组
vert:布尔值,True 绘制纵向箱线图,False 绘制横向箱线图
notch:布尔值,是否绘制带 V 型凹口的箱线图(用于展示中位数的置信区间)
patch_artist:布尔值,若为 True,则填充箱体内部颜色;若为 False,仅绘制线框
tick_labels:各个箱线序列的名称标签
showmeans:布尔值,是否额外标出均值点

代码示例

group1 = [65, 72, 75, 80, 82, 88, 95]
group2 = [50, 60, 70, 75, 78, 85, 99]
group3 = [78, 82, 84, 86, 89, 90, 92]
data = [group1, group2, group3]

# 绘制箱线图
plt.figure(figsize=(7, 4))
plt.boxplot(data, tick_labels=['Group A', 'Group B', 'Group C'], 
            patch_artist=True, showmeans=True)

plt.title('Performance Distribution Across Groups')
plt.ylabel('Scores')
plt.grid(axis='y', linestyle=':', alpha=0.7)
plt.show()

输出结果:

小结

图表类型 核心 API 典型应用场景 关键参数
折线图 plt.plot() 时间序列变化趋势 linestyle, marker
柱状图 plt.bar() / plt.barh() 分类数值大小比较 width, bottom
饼图 plt.pie() 构成与占比分析 autopct, explode
散点图 plt.scatter() 双变量相关性与分布 s, c, cmap, alpha
箱线图 plt.boxplot() 分位数分布与异常值识别 patch_artist, vert

三、面向对象接口

如果说 pyplot 是 Matplotlib 的快捷模式,那么面向对象接口才是 Matplotlib 的底层完全形态。在企业级工程实践、自动化报表开发以及生产环境中,面向对象接口是更为推荐的代码规范


1. Figure 与 Axes

理解面向对象接口,关键在于理清两个核心概念:Figure(画布)Axes(坐标系/子图)

1. Figure 对象(画布)

  • 定位:包含所有图形元素的顶层容器

  • 职责:管理整幅图的大小、背景色、分辨率,以及管理画板上的所有子图

2. Axes 对象(坐标系/子图)

  • 定位:真正承载数据图形(折线、柱体、散点等)的区域

  • 职责:拥有独立的 X/Y 轴、刻度、标签、标题与图例。一张 Figure 上可以包含一个或多个 Axes


2. plt.subplots()

在面向对象风格中,最经典、使用频率最高的初始化方法是调用 plt.subplots()

fig, ax = plt.subplots(nrows=1, ncols=1, *, sharex=False, 
                       sharey=False, figsize=None, dpi=None, **kwargs)

参数说明:
nrows, ncols:子图网格的行数与列数
figsize:画布尺寸,单位为英寸
sharex, sharey:是否共享 X 轴或 Y 轴的刻度与范围,常用于多子图对比分析
dpi:图像分辨率,默认通常为 100

返回值;
fig:返回创建的 figure 对象
ax:若为 1x1 布局,返回单个 axes 对象
    若为多子图布局,返回由 axes 对象组成的 NumPy 数组

3. 为什么推荐面向对象接口

在实际项目中,团队通常强制要求采用面向对象风格,其核心逻辑在于以下四个维度:

1. 消除隐式状态的副作用

pyplot 依赖全局状态机,在执行多图绘制、循环画图或并发任务时,很容易因为 "画布/坐标系" 未重置而导致绘制内容错位。面向对象接口中,所有操作都显式绑定在具体的对象变量上,逻辑透明且线程安全

2. 多子图支持

在涉及多张子图排版时,面向对象接口可以通过数组索引精确控制每一个子图:

fig, axes = plt.subplots(2, 2, figsize=(10, 8))

# 显式控制各个子图,彼此互不干扰
axes[0, 0].plot(x, y1)
axes[0, 1].bar(x, y2)
axes[1, 0].scatter(x, y3)
axes[1, 1].boxplot(y4)

3. 方法命名更严谨

在 Axes 对象中,属性设置采用了面向对象语言通用的 Getter/Setter 范式。相比于 pyplot 的无规律命名,面向对象 API 更加规范:

绘图需求 pyplot 接口 面向对象 API
设置标题 plt.title() ax.set_title()
设置 X 轴标签 plt.xlabel() ax.set_xlabel()
设置 Y 轴范围 plt.ylim() ax.set_ylim()
设置 X 轴刻度 plt.xticks() ax.set_xticks()
显示网格 plt.grid() ax.grid()

4. 便于封装与集成

当需要把绘图逻辑封装为函数、类或集成到 Web 后端以及 Streamlit 数据大屏中时,面向对象风格能够直接传递 fig 或 ax 句柄,从而实现图表样式的模块化定制与灵活复用


4. 代码案例

以下是用面向对象 API 绘制双子图对比的范例:

# 1. 准备数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 2. 创建画布与 1 行 2 列的子图对象
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4.5), sharey=True)

# 3. 绘制第一个子图
ax1.plot(x, y1, color='#1f77b4', label='Sin(x)')
ax1.set_title('Sine Wave')
ax1.grid(True, linestyle='--')

# 4. 绘制第二个子图
ax2.plot(x, y2, color='#ff7f0e', linestyle='--', label='Cos(x)')
ax2.set_title('Cosine Wave')
ax2.grid(True, linestyle='--')

plt.show()

输出结果:

四、图形美化

在实际的数据分析开发中,仅绘制出图形的骨架是远远不够的。未经过美化的原始图表往往缺乏上下文、字号过小或缺乏必要的辅助元素,极易造成阅读障碍

在日常开发中,设置画布尺寸标题与坐标轴标签图例以及网格辅助线是几乎每天都会用到的配置项。本章将逐一介绍这些元素的配置 API 与美化技巧


1. 画布尺寸设置

画布尺寸决定了图表呈现的比例。合理的尺寸能够避免元素拥挤或布局变形

API 方法与参数

在面向对象接口中,通常在创建 Figure 对象时指定 figsize:

fig, ax = plt.subplots(figsize=(float, float), dpi=int)

figsize:以元组形式传入 (宽度, 高度),单位为英寸。常见比例有:
    (8, 5) 或 (8, 4.5):标准横屏比例(16:9 或 16:10)
    (12, 6):宽屏比例
    (6, 6):等宽正方形比例
dpi:每英寸点数。开发展示通常设为 100,若用于高清印刷或导出可设置为 300 及以上

2. 标题与坐标轴标签(title / xlabel / ylabel)

文本标注是让图表具备自我解释能力的基础

API 方法签名

# 面向对象 API
ax.set_title(label, fontsize=12, fontweight='bold', pad=15, color='black')
ax.set_xlabel(xlabel, fontsize=10, labelpad=10, color='gray')
ax.set_ylabel(ylabel, fontsize=10, labelpad=10, color='gray')

fontsize:字号大小,可用数值或预设字符串(如 'large')
fontweight:字体粗细,如 'normal'、'bold'
pad / labelpad:坐标轴的边距像素值
color:文本颜色

3. 图例配置(legend)

当图表中包含多条数据序列或多个对比分类时,图例(Legend)是识别不同数据的桥梁

API 方法签名

ax.legend(loc='best', frameon=True, fontsize=10, ncol=1, bbox_to_anchor=None)

loc:图例在子图区域内的摆放位置。常用取值包括:
    'best':系统自动选择覆盖数据最少的最佳位置
    'upper right', 'upper left', 'lower right', 'lower left', 'center'。
bbox_to_anchor:用于将图例定位到子图区域之外
frameon:布尔值,是否保留图例的外框线
ncol:图例的列数。当类别较多且采用水平排版时,可设为 ncol=2 或 ncol=3

只有在调用绘图方法(如 ax.plot() 或 ax.bar())时显式指定了 label='标签名' 参数,调用 ax.legend() 才能正确渲染图例


4. 网格辅助线(grid)

合理的网格线能提升读者对数据点具体数值的读数精度

API 方法签名

ax.grid(visible=True, which='major', axis='both', 
        linestyle='--', alpha=0.5, color='gray')

visible:是否显示网格线
axis:控制网格线的方向,可选 'both'(双向)、'x'(仅竖线)、'y'(仅横线)
linestyle:网格线的线型,通常建议使用虚线 ':' 或 '--'
alpha:透明度(0.0 至 1.0)

总结

本章围绕 Matplotlib 展开,学习了状态接口和面向对象接口两种绘图方式,并掌握了折线图、柱状图、饼图、散点图、箱线图等常见图表的绘制方法。同时,我们还学习了标题、坐标轴、图例、网格等图形美化技巧,能够根据不同的数据特点绘制更加清晰、美观的数据图表

下一篇将学习 Seaborn 统计可视化,进一步了解 Seaborn 在统计图表绘制方面的优势,并掌握单变量、双变量和多变量数据的可视化方法,使数据分析结果更加直观、易于理解

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐