Matplotlib 3.6.0 新特性 (2022 年 9 月 15 日)#
有关自上次修订以来的所有问题和拉取请求的列表,请参阅 3.10.0 版本 (2024 年 12 月 13 日) 的 GitHub 统计信息。
图形和轴的创建/管理#
subplots
、subplot_mosaic
接受 height_ratios 和 width_ratios 参数#
可以通过将 height_ratios 和 width_ratios 关键字参数传递给方法来控制 subplots
和 subplot_mosaic
中列和行的相对宽度和高度
fig = plt.figure()
axs = fig.subplots(3, 1, sharex=True, height_ratios=[3, 1, 1])
以前,这需要在 gridspec_kw 参数中传递比例。
fig = plt.figure()
axs = fig.subplots(3, 1, sharex=True,
gridspec_kw=dict(height_ratios=[3, 1, 1]))
约束布局不再被认为是实验性的#
约束布局引擎和 API 不再被认为是实验性的。未经弃用期,不允许对行为和 API 进行任意更改。
新的 layout_engine
模块#
Matplotlib 带有 tight_layout
和 constrained_layout
布局引擎。提供了一个新的 layout_engine
模块,允许下游库编写自己的布局引擎,并且 Figure
对象现在可以将 LayoutEngine
子类作为 layout 参数的参数。
固定纵横比的 Axes 的压缩布局#
现在可以使用 fig, axs = plt.subplots(2, 3, layout='compressed')
将具有固定纵横比的 Axes 的简单排列打包在一起。
使用 layout='tight'
或 'constrained'
,具有固定纵横比的 Axes 可以在彼此之间留下很大的间隙。
使用 layout='compressed'
布局会减少 Axes 之间的空间,并将额外的空间添加到外部边距。
有关更多详细信息,请参阅 固定纵横比 Axes 的网格:“压缩”布局。
现在可以删除布局引擎#
现在可以通过使用 'none'
调用 Figure.set_layout_engine
来删除 Figure 上的布局引擎。这在计算布局后,为了减少计算量可能会很有用,例如,对于后续的动画循环。
之后可以设置不同的布局引擎,只要它与之前的布局引擎兼容即可。
Axes.inset_axes
的灵活性#
matplotlib.axes.Axes.inset_axes
现在接受 projection、polar 和 axes_class 关键字参数,以便可以返回 matplotlib.axes.Axes
的子类。
fig, ax = plt.subplots()
ax.plot([0, 2], [1, 2])
polar_ax = ax.inset_axes([0.75, 0.25, 0.2, 0.2], projection='polar')
polar_ax.plot([0, 2], [1, 2])
WebP 现在是受支持的输出格式#
现在可以使用 .webp
文件扩展名保存为 WebP 格式的图形,或将 format='webp'
传递给 savefig
。这依赖于 Pillow 对 WebP 的支持。
垃圾回收不再在图形关闭时运行#
Matplotlib 有大量的循环引用(Figure 和 Manager 之间,Axes 和 Figure 之间,Axes 和 Artist 之间,Figure 和 Canvas 之间等),因此当用户删除对 Figure 的最后一个引用(并从 pyplot 的状态中清除它)时,这些对象不会立即被删除。
为了解决这个问题,我们长期以来(自 2004 年之前)在关闭代码中有一个 gc.collect
(仅针对最低的两代),以便及时清理自身。然而,这既没有做我们想要的事情(因为我们的大多数对象实际上会幸存下来),并且由于清除了第一代,使我们面临无界内存使用的情况。
在创建图形和销毁图形之间存在非常紧密的循环的情况下(例如 plt.figure(); plt.close()
),第一代永远不会增长到足够大,以至于 Python 考虑对更高世代运行收集。这将导致无界内存使用,因为长期存在的对象永远不会被重新考虑以查找引用循环,因此永远不会被删除。
现在,当图形关闭时,我们不再进行任何垃圾回收,而是依赖 Python 自动决定定期运行垃圾回收。如果您有严格的内存要求,您可以自己调用 gc.collect
,但这可能会在紧密的计算循环中对性能产生影响。
绘图方法#
条纹线(实验性)#
plot
的新 gapcolor 参数支持创建条纹线。
x = np.linspace(1., 3., 10)
y = x**3
fig, ax = plt.subplots()
ax.plot(x, y, linestyle='--', color='orange', gapcolor='blue',
linewidth=3, label='a striped line')
ax.legend()
bxp
和 boxplot
中箱形图和须状图中的自定义帽宽#
bxp
和 boxplot
的新 capwidths 参数允许控制箱形图和须状图中帽的宽度。
x = np.linspace(-7, 7, 140)
x = np.hstack([-25, x, 25])
capwidths = [0.01, 0.2]
fig, ax = plt.subplots()
ax.boxplot([x, x], notch=True, capwidths=capwidths)
ax.set_title(f'{capwidths=}')
更容易标记条形图中的条形#
bar
和 barh
的 label 参数现在可以传递条形的标签列表。该列表的长度必须与 x 相同,并为各个条形添加标签。重复的标签不会被去重,并且会导致重复的标签条目,因此最好在条形的样式也不同时使用(例如,将列表传递给 color,如下所示)。
x = ["a", "b", "c"]
y = [10, 20, 15]
color = ['C0', 'C1', 'C2']
fig, ax = plt.subplots()
ax.bar(x, y, color=color, label=x)
ax.legend()
颜色条刻度的新样式格式字符串#
colorbar
(和其他颜色条方法)的 format 参数现在接受 {}
样式的格式字符串。
fig, ax = plt.subplots()
im = ax.imshow(z)
fig.colorbar(im, format='{x:.2e}') # Instead of '%.2e'
可以单独设置负等高线的线型#
可以通过将 negative_linestyles 参数传递给 Axes.contour
来设置负等高线的线型。以前,此样式只能通过 rcParams["contour.negative_linestyle"]
(默认值:'dashed'
)全局设置。
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, axs = plt.subplots(1, 2)
CS = axs[0].contour(X, Y, Z, 6, colors='k')
axs[0].clabel(CS, fontsize=9, inline=True)
axs[0].set_title('Default negative contours')
CS = axs[1].contour(X, Y, Z, 6, colors='k', negative_linestyles='dotted')
axs[1].clabel(CS, fontsize=9, inline=True)
axs[1].set_title('Dotted negative contours')
通过 ContourPy 改进四边形等高线计算#
等高线函数 contour
和 contourf
有一个新的关键字参数 algorithm 来控制用于计算等高线的算法。有四种算法可供选择,默认值是使用 algorithm='mpl2014'
,这与 Matplotlib 自 2014 年以来使用的算法相同。
以前,Matplotlib 使用自己的 C++ 代码来计算四边形网格的等高线。现在,改用外部库 ContourPy。
此时 algorithm 关键字参数的其他可能值包括 'mpl2005'
、'serial'
和 'threaded'
;有关详细信息,请参阅 ContourPy 文档。
注意
由 algorithm='mpl2014'
生成的等高线和多边形与此更改之前生成的等高线和多边形在浮点精度范围内相同。例外情况是重复的点,即包含相邻(x,y)点的等高线相同;以前,重复的点被删除,现在保留它们。受此影响的等高线将产生相同的视觉输出,但是等高线中的点数会更多。
通过使用 clabel
获得的等高线标签的位置也可能不同。
errorbar
支持 markerfacecoloralt#
markerfacecoloralt 参数现在从 Axes.errorbar
传递到折线绘图器。该文档现在准确列出了哪些属性传递给 Line2D
,而不是声称所有关键字参数都被传递。
x = np.arange(0.1, 4, 0.5)
y = np.exp(-x)
fig, ax = plt.subplots()
ax.errorbar(x, y, xerr=0.2, yerr=0.4,
linestyle=':', color='darkgrey',
marker='o', markersize=20, fillstyle='left',
markerfacecolor='tab:blue', markerfacecoloralt='tab:orange',
markeredgecolor='tab:brown', markeredgewidth=2)
streamplot
可以禁用流线中断#
现在可以指定流线图具有连续、不中断的流线。以前,流线会结束以限制单个网格单元内的线条数量。请参见下面的图之间的差异
新的轴刻度 asinh
(实验性)#
新的 asinh
轴刻度提供了 symlog
的替代方法,可以在刻度的准线性和渐近对数区域之间平滑过渡。这基于反双曲正弦变换,该变换允许绘制跨越多个数量级的正值和负值。
stairs(..., fill=True)
通过设置线宽来隐藏补丁边缘#
stairs(..., fill=True)
以前会通过设置 edgecolor="none"
来隐藏 Patch 边缘。因此,稍后在 Patch 上调用 set_color()
会使 Patch 看起来更大。
现在,通过使用 linewidth=0
,可以防止这种明显的尺寸变化。同样,调用 stairs(..., fill=True, linewidth=3)
的行为会更加透明。
修复 Patch 类的虚线偏移量#
以前,当使用虚线元组在 Patch
对象上设置线条样式时,会忽略偏移量。现在,偏移量按预期应用于 Patch,并且可以像 Line2D
对象一样使用。
矩形补丁旋转点#
现在可以使用 rotation_point 参数将 Rectangle
的旋转点设置为“xy”、“center”或数字的 2 元组。
颜色和颜色映射#
颜色序列注册表#
颜色序列注册表 ColorSequenceRegistry
包含 Matplotlib 已知名称的颜色序列(即,简单的列表)。这通常不会直接使用,而是通过 matplotlib.color_sequences
的通用实例使用。
用于创建不同查找表大小的颜色映射方法#
新的方法 Colormap.resampled
创建了一个新的 Colormap
实例,具有指定的查找表大小。这是通过 get_cmap
操作查找表大小的替代方法。
使用
get_cmap(name).resampled(N)
代替
get_cmap(name, lut=N)
使用字符串设置规范#
现在可以使用相应比例的字符串名称设置规范(例如,在图像上),例如 imshow(array, norm="log")
。请注意,在这种情况下,也可以传递 vmin 和 vmax,因为会在后台创建一个新的 Norm 实例。
标题、刻度和标签#
plt.xticks
和 plt.yticks
支持 minor 关键字参数#
现在可以使用 pyplot.xticks
和 pyplot.yticks
通过设置 minor=True
来设置或获取次刻度。
plt.figure()
plt.plot([1, 2, 3, 3.5], [2, 1, 0, -0.5])
plt.xticks([1, 2, 3], ["One", "Zwei", "Trois"])
plt.xticks([np.sqrt(2), 2.5, np.pi],
[r"$\sqrt{2}$", r"$\frac{5}{2}$", r"$\pi$"], minor=True)
图例#
图例可以控制标题和句柄的对齐方式#
Legend
现在支持通过关键字参数 alignment 控制标题和句柄的对齐方式。您还可以使用 Legend.set_alignment
来控制现有图例的对齐方式。
fig, axs = plt.subplots(3, 1)
for i, alignment in enumerate(['left', 'center', 'right']):
axs[i].plot(range(10), label='test')
axs[i].legend(title=f'{alignment=}', alignment=alignment)
legend
的 ncol 关键字参数重命名为 ncols#
为了与 subplots
和 GridSpec
的 ncols 和 nrows 关键字保持一致,legend
中用于控制列数的 ncol 关键字参数被重命名为 ncols。为了向后兼容,仍然支持 ncol,但不建议使用。
标记#
marker
现在可以设置为字符串 "none"#
字符串 "none" 表示 *无标记*,与其他支持小写版本的 API 一致。建议使用 "none" 而不是 "None",以避免与 None 对象混淆。
自定义 MarkerStyle
的连接和端点样式#
新的 MarkerStyle
参数允许控制连接样式和端点样式,并允许用户提供要应用于标记的转换(例如,旋转)。
from matplotlib.markers import CapStyle, JoinStyle, MarkerStyle
from matplotlib.transforms import Affine2D
fig, axs = plt.subplots(3, 1, layout='constrained')
for ax in axs:
ax.axis('off')
ax.set_xlim(-0.5, 2.5)
axs[0].set_title('Cap styles', fontsize=14)
for col, cap in enumerate(CapStyle):
axs[0].plot(col, 0, markersize=32, markeredgewidth=8,
marker=MarkerStyle('1', capstyle=cap))
# Show the marker edge for comparison with the cap.
axs[0].plot(col, 0, markersize=32, markeredgewidth=1,
markerfacecolor='none', markeredgecolor='lightgrey',
marker=MarkerStyle('1'))
axs[0].annotate(cap.name, (col, 0),
xytext=(20, -5), textcoords='offset points')
axs[1].set_title('Join styles', fontsize=14)
for col, join in enumerate(JoinStyle):
axs[1].plot(col, 0, markersize=32, markeredgewidth=8,
marker=MarkerStyle('*', joinstyle=join))
# Show the marker edge for comparison with the join.
axs[1].plot(col, 0, markersize=32, markeredgewidth=1,
markerfacecolor='none', markeredgecolor='lightgrey',
marker=MarkerStyle('*'))
axs[1].annotate(join.name, (col, 0),
xytext=(20, -5), textcoords='offset points')
axs[2].set_title('Arbitrary transforms', fontsize=14)
for col, (size, rot) in enumerate(zip([2, 5, 7], [0, 45, 90])):
t = Affine2D().rotate_deg(rot).scale(size)
axs[2].plot(col, 0, marker=MarkerStyle('*', transform=t))
字体和文本#
字体回退#
现在可以指定字体系列的列表,Matplotlib 将按顺序尝试它们以查找所需的字形。
plt.rcParams["font.size"] = 20
fig = plt.figure(figsize=(4.75, 1.85))
text = "There are 几个汉字 in between!"
fig.text(0.05, 0.65, text, family=["Noto Sans CJK JP", "Noto Sans TC"])
fig.text(0.05, 0.45, text, family=["DejaVu Sans", "Noto Sans CJK JP", "Noto Sans TC"])
这目前适用于 Agg(和所有 GUI 嵌入)、svg、pdf、ps 和内联后端。
可用字体名称列表#
现在可以轻松访问可用字体列表。要获取 Matplotlib 中可用字体名称的列表,请使用
from matplotlib import font_manager
font_manager.get_font_names()
math_to_image
现在有一个 color 关键字参数#
为了方便地支持依赖于 Matplotlib 的 MathText 渲染生成方程图像的外部库,math_to_image
添加了一个 color 关键字参数。
from matplotlib import mathtext
mathtext.math_to_image('$x^2$', 'filename.png', color='Maroon')
活动 URL 区域随链接文本旋转#
当在图中旋转链接文本时,活动 URL 区域现在将包含旋转的链接区域。以前,活动区域保持在原始的未旋转位置。
rcParams 改进#
允许全局设置图形标签大小和粗细,并与标题分开#
对于图形标签,Figure.supxlabel
和 Figure.supylabel
,可以使用 rcParams["figure.labelsize"]
(默认值:'large'
)和 rcParams["figure.labelweight"]
(默认值:'normal'
)设置大小和粗细,使其与图形标题分开。
# Original (previously combined with below) rcParams:
plt.rcParams['figure.titlesize'] = 64
plt.rcParams['figure.titleweight'] = 'bold'
# New rcParams:
plt.rcParams['figure.labelsize'] = 32
plt.rcParams['figure.labelweight'] = 'bold'
fig, axs = plt.subplots(2, 2, layout='constrained')
for ax in axs.flat:
ax.set(xlabel='xlabel', ylabel='ylabel')
fig.suptitle('suptitle')
fig.supxlabel('supxlabel')
fig.supylabel('supylabel')
请注意,如果您已更改 rcParams["figure.titlesize"]
(默认值:'large'
) 或 rcParams["figure.titleweight"]
(默认值:'normal'
),为了获得与过去行为一致的结果,现在还必须更改引入的参数。
可以在全局范围内禁用 Mathtext 解析#
可以使用 rcParams["text.parse_math"]
(默认值:True
) 设置来禁用所有 Text
对象(最值得注意的是来自 Axes.text
方法的对象)中的 mathtext 解析。
matplotlibrc 中的双引号字符串#
现在可以在字符串周围使用双引号。这允许在字符串中使用“#”字符。如果没有引号,“#”会被解释为注释的开始。特别是,您现在可以定义十六进制颜色。
grid.color: "#b0b0b0"
3D 轴改进#
主平面视角标准化#
当在主视角平面之一(即垂直于 XY、XZ 或 YZ 平面)中查看 3D 图时,轴将显示在标准位置。有关 3D 视角的更多信息,请参阅 mplot3d 视角 和 主 3D 视角平面。
3D 相机的自定义焦距#
现在,3D 轴可以通过指定虚拟相机的焦距来更好地模拟真实世界的相机。默认焦距 1 对应于 90° 的视野 (FOV),并且向后兼容现有的 3D 图。1 和无穷大之间的增加的焦距会“展平”图像,而 1 和 0 之间的减小的焦距会夸大透视效果,并使图像具有更明显的深度。
可以通过以下等式从所需的 FOV 计算焦距
from mpl_toolkits.mplot3d import axes3d
X, Y, Z = axes3d.get_test_data(0.05)
fig, axs = plt.subplots(1, 3, figsize=(7, 4),
subplot_kw={'projection': '3d'})
for ax, focal_length in zip(axs, [0.2, 1, np.inf]):
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
ax.set_proj_type('persp', focal_length=focal_length)
ax.set_title(f"{focal_length=}")
3D 图获得了第三个“滚动”视角#
现在可以通过添加第三个滚动角度从任何方向查看 3D 图,该角度会围绕观察轴旋转图。使用鼠标进行的交互式旋转仍然仅控制仰角和方位角,这意味着此功能与以编程方式创建更复杂相机角度的用户相关。默认滚动角度 0 向后兼容现有的 3D 图。
from mpl_toolkits.mplot3d import axes3d
X, Y, Z = axes3d.get_test_data(0.05)
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
ax.view_init(elev=0, azim=0, roll=30)
ax.set_title('elev=0, azim=0, roll=30')
3D 图的相等纵横比#
用户可以将 3D 图的 X、Y、Z 轴的纵横比设置为“equal”、“equalxy”、“equalxz”或“equalyz”,而不是默认的“auto”。
from itertools import combinations, product
aspects = [
['auto', 'equal', '.'],
['equalxy', 'equalyz', 'equalxz'],
]
fig, axs = plt.subplot_mosaic(aspects, figsize=(7, 6),
subplot_kw={'projection': '3d'})
# Draw rectangular cuboid with side lengths [1, 1, 5]
r = [0, 1]
scale = np.array([1, 1, 5])
pts = combinations(np.array(list(product(r, r, r))), 2)
for start, end in pts:
if np.sum(np.abs(start - end)) == r[1] - r[0]:
for ax in axs.values():
ax.plot3D(*zip(start*scale, end*scale), color='C0')
# Set the aspect ratios
for aspect, ax in axs.items():
ax.set_box_aspect((3, 4, 5))
ax.set_aspect(aspect)
ax.set_title(f'set_aspect({aspect!r})')
交互式工具改进#
旋转、纵横比校正和添加/删除状态#
RectangleSelector
和 EllipseSelector
现在可以在 -45° 和 45° 之间进行交互式旋转。范围限制当前由实现决定。通过按下 r 键(“r”是 state_modifier_keys 中映射到“rotate”的默认键)或调用 selector.add_state('rotate')
来启用或禁用旋转。
当使用“square”状态时,现在可以考虑轴的纵横比。通过在初始化选择器时指定 use_data_coordinates='True'
来启用此功能。
除了使用 state_modifier_keys 中定义的修改键交互式更改选择器状态外,现在可以使用 add_state 和 remove_state 方法以编程方式更改选择器状态。
from matplotlib.widgets import RectangleSelector
values = np.arange(0, 100)
fig = plt.figure()
ax = fig.add_subplot()
ax.plot(values, values)
selector = RectangleSelector(ax, print, interactive=True,
drag_from_anywhere=True,
use_data_coordinates=True)
selector.add_state('rotate') # alternatively press 'r' key
# rotate the selector interactively
selector.remove_state('rotate') # alternatively press 'r' key
selector.add_state('square')
MultiCursor
现在支持跨多个图形拆分的轴#
以前,只有当所有目标轴属于同一个图形时,MultiCursor
才起作用。
由于此更改,MultiCursor
构造函数的第一个参数已不再使用(它以前是所有轴的联合画布,但画布现在直接从轴列表中推断出来)。
PolygonSelector
边界框#
PolygonSelector
现在具有 draw_bounding_box 参数,当设置为 True
时,将在多边形完成后在多边形周围绘制一个边界框。可以调整边界框的大小和移动边界框,从而轻松调整多边形的点的大小。
设置 PolygonSelector
顶点#
现在可以使用 PolygonSelector.verts
属性以编程方式设置 PolygonSelector
的顶点。以这种方式设置顶点将重置选择器,并使用提供的顶点创建一个新的完整选择器。
SpanSelector
小部件现在可以捕捉到指定的值#
SpanSelector
小部件现在可以捕捉到由 snap_values 参数指定的值。
更多工具栏图标针对深色主题进行了样式设置#
在 macOS 和 Tk 后端上,当使用深色主题时,工具栏图标现在会反转。
特定于平台的更改#
Wx 后端使用标准工具栏#
工具栏不是使用自定义大小器设置,而是作为标准工具栏设置在 Wx 窗口上。
macosx 后端的改进#
修饰键处理更加一致#
macosx 后端现在以与其他后端更一致的方式处理修饰键。有关更多信息,请参阅事件连接中的表格。
savefig.directory
rcParam 支持#
macosx 后端现在将遵循 rcParams["savefig.directory"]
(默认值: '~'
) 设置。如果设置为非空字符串,则保存对话框将默认使用此目录,并保留后续更改的保存目录。
figure.raise_window
rcParam 支持#
macosx 后端现在将遵循 rcParams["figure.raise_window"]
(默认值: True
) 设置。如果设置为 False,则图形窗口在更新时不会被提升到顶部。
全屏切换支持#
与其他后端一样,macosx 后端现在支持切换全屏视图。默认情况下,可以通过按 f 键切换此视图。
改进的动画和缓冲支持#
macosx 后端已得到改进,以修复缓冲、带有新艺术家的动画帧,并减少不必要的绘制调用。
在 Qt 后端上应用 macOS 应用程序图标#
在 macOS 上使用基于 Qt 的后端时,现在将设置应用程序图标,就像在其他后端/平台上一样。
新的最低 macOS 版本#
macosx 后端现在需要 macOS >= 10.12。
Windows on ARM 支持#
已添加对 arm64 目标上的 Windows 的初步支持。此支持需要 FreeType 2.11 或更高版本。
目前还没有可用的二进制 wheel,但可以从源代码构建。