Matplotlib 中 5 套核心坐标系统的原理与应用
在 Python 数据可视化库 Matplotlib 中,理解坐标系统(Transforms)是掌握高级绘图技巧的关键。许多开发者在使用 plt.text、ax.annotate 或自定义图形元素时,常因混淆不同坐标系而导致位置偏移或缩放异常。本文将深入解析 Matplotlib 中的五大坐标系统,通过代码示例与原理说明,帮助读者彻底理清各类坐标的转换逻辑。
本文详细解析了 Matplotlib 中的五种核心坐标系统:显示空间、Figure 空间、数据空间、Axes 空间及混合空间。通过对比各系统的单位、基准对象及应用场景,并结合代码示例说明了如何使用 transData、transAxes 等属性进行坐标转换。文章重点阐述了在不同缩放与布局需求下选择合适坐标系的策略,提供了混合坐标系的构建方法及常见问题的解决方案,旨在帮助开发者精准控制图表元素的定位与渲染。

在 Python 数据可视化库 Matplotlib 中,理解坐标系统(Transforms)是掌握高级绘图技巧的关键。许多开发者在使用 plt.text、ax.annotate 或自定义图形元素时,常因混淆不同坐标系而导致位置偏移或缩放异常。本文将深入解析 Matplotlib 中的五大坐标系统,通过代码示例与原理说明,帮助读者彻底理清各类坐标的转换逻辑。
单位:像素 (px)
这是最底层的坐标系统,所有其他坐标最终都会被转换为显示空间才能在屏幕上渲染。它对应于图像的实际像素尺寸。
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(5, 6), facecolor='skyblue')
ax.set_facecolor('orange')
# 获取 Figure 的窗口范围(像素)
box_fig = fig.get_window_extent()
print(f"Figure 宽/高 (px): {box_fig.width}, {box_fig.height}")
print(f"Figure 起点 (x0, y0): {box_fig.x0}, {box_fig.y0}")
# 获取 Axes 的窗口范围(像素)
box_ax = ax.get_window_extent()
print(f"Axes 宽/高 (px): {box_ax.width}, {box_ax.height}")
print(f"Axes 起点 (x0, y0): {box_ax.x0}, {box_ax.y0}")
# 验证 DPI 转换
print(f"DPI: {fig.dpi}")
print(f"5x6 英寸转像素:{fig.dpi_scale_trans.transform((5, 6))}")
注意:显示坐标不适合直接用于绘图,因为当用户缩放图像时,像素坐标会发生变化,导致图形元素位置错乱。通常仅用于获取布局信息。
单位:百分比 (fraction, 0-1)
该坐标系以整个 Figure 画布为基准。左下角为 (0, 0),右上角为 (1, 1)。无论子图如何排列,Figure 坐标始终相对于整个画布。
import matplotlib.pyplot as plt
fig, ax = plt.subplots(facecolor='skyblue')
ax.set_facecolor('orange')
# 使用 figure.transFigure 定位文本
plt.text(0.5, 0.95, 'Figure Center Top',
transform=fig.transFigure,
ha='center', va='top', fontsize=14, color='white')
# 绝对像素定位 (transform=None 等同于 display space)
plt.text(200, 300, 'Absolute Pixel',
transform=None,
ha='center', va='center', color='red')
plt.show()
单位:由数据决定 (整数或浮点数)
这是最常用的坐标系统,基于 xlim 和 ylim 定义的数据范围。默认情况下,绘图命令(如 plot, scatter)均使用此系统。
ax.transData 将数据坐标转换为显示坐标。import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 10, 0.005)
y = np.exp(-x / 2.) * np.sin(2 * np.pi * x)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
# 显式指定 transData
ax.scatter([2], [0.5], color='red', transform=ax.transData)
plt.show()
单位:百分比 (fraction, 0-1)
该坐标系以当前的 Axes 子图为基准。左下角为 (0, 0),右上角为 (1, 1)。即使数据范围变化,(0.5, 0.5) 始终位于子图中心。
import random
import matplotlib.pyplot as plt
fig = plt.figure()
for i, label in enumerate(('A', 'B', 'C', 'D')):
ax = fig.add_subplot(2, 2, i + 1)
# 使用 transAxes 将文本固定在左上角
ax.text(0.05, 0.95, label,
transform=ax.transAxes,
fontsize=16, fontweight='bold',
va='top', color='red')
# 随机设置数据范围,观察文本位置是否变化
ax.set_xlim([random.randint(0, 50), random.randint(50, 100)])
ax.set_ylim([0, random.randint(10, 100)])
ax.set_facecolor('yellowgreen')
plt.tight_layout()
plt.show()
单位:X 轴与 Y 轴单位可独立指定
允许在一个坐标轴上使用数据坐标,另一个轴上使用 Axes 或 Figure 坐标。这对于创建跨越特定数据范围但高度固定的区域非常有用。
ax.get_xaxis_transform(): X 为数据坐标,Y 为 Axes 坐标 (0-1)。ax.get_yaxis_transform(): X 为 Axes 坐标 (0-1),Y 为数据坐标。matplotlib.transforms.blended_transform_factory: 自定义组合。import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax.plot(x, y)
# 在数据 x=5 处画一条垂直线,y 从 0 到 1 (Axes 坐标)
ax.axvline(5, color='red', linestyle='--',
transform=ax.get_xaxis_transform())
# 使用 blended_transform_factory 自定义
from matplotlib.transforms import blended_transform_factory
trans = blended_transform_factory(ax.transData, ax.transAxes)
ax.plot([0, 10], [0.5, 0.5], transform=trans, color='green', lw=3)
plt.show()
| 坐标系统 | 单位 | 基准对象 | 典型用途 | 变换属性 |
|---|---|---|---|---|
| Display Space | 像素 (px) | 屏幕/文件 | 获取布局信息 | ax.transData 最终输出 |
| Figure Space | 百分比 (0-1) | 整个 Figure | 全局标题、水印 | fig.transFigure |
| Data Space | 数据值 | 数据范围 | 常规绘图、散点 | ax.transData |
| Axes Space | 百分比 (0-1) | 当前 Axes | 子图内固定标注 | ax.transAxes |
| Blended Space | 混合 | 数据/Axes | 跨域高亮、辅助线 | get_xaxis_transform |
transData;若希望标注固定在画布位置,请使用 transAxes 或 transFigure。ax.xaxis.set_label_coords() 默认使用 Axes 坐标,可通过 transform 参数修改。transform 计算,建议预先计算关键坐标点。掌握 Matplotlib 的坐标系统转换机制,能够显著提升图表的可定制性与专业性。在实际开发中,建议优先使用 transData 处理数据关系,使用 transAxes 处理布局关系,并在必要时结合 blended_transform 实现特殊效果。理解这些底层原理,有助于解决绝大多数绘图定位问题。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online