注意
转到末尾 下载完整的示例代码。
Matplotlib 中的文本#
Matplotlib 绘图和文本处理简介。
Matplotlib 提供了广泛的文本支持,包括对数学表达式的支持、用于光栅和矢量输出的 TrueType 支持、带有任意旋转的换行符分隔文本以及 Unicode 支持。
因为它直接将字体嵌入到输出文档中,例如,对于 PostScript 或 PDF,你在屏幕上看到的内容就是你在硬拷贝中得到的内容。 FreeType 支持生成非常漂亮的抗锯齿字体,即使在较小的光栅尺寸下也能看起来很好。Matplotlib 包含它自己的 matplotlib.font_manager
(感谢 Paul Barrett),它实现了一个跨平台、符合 W3C 标准的字体查找算法。
用户可以对文本属性(字体大小、字体粗细、文本位置和颜色等)进行大量控制,在 rc 文件 中设置了合理的默认值。重要的是,对于那些对数学或科学图形感兴趣的人来说,Matplotlib 实现了许多 TeX 数学符号和命令,支持在你的图形中的任何地方使用 数学表达式。
基本文本命令#
以下命令用于在隐式和显式接口中创建文本(有关权衡的解释,请参阅 Matplotlib 应用程序接口 (API))。
隐式 API |
显式 API |
描述 |
---|---|---|
在 |
||
在 |
||
在 |
||
在 |
||
在 |
||
在 |
||
在 |
所有这些函数都会创建一个并返回一个 Text
实例,该实例可以使用各种字体和其他属性进行配置。下面的示例展示了所有这些命令的实际操作,并在接下来的部分中提供更多详细信息。
import matplotlib.pyplot as plt
import matplotlib
fig = plt.figure()
ax = fig.add_subplot()
fig.subplots_adjust(top=0.85)
# Set titles for the figure and the subplot respectively
fig.suptitle('bold figure suptitle', fontsize=14, fontweight='bold')
ax.set_title('axes title')
ax.set_xlabel('xlabel')
ax.set_ylabel('ylabel')
# Set both x- and y-axis limits to [0, 10] instead of default [0, 1]
ax.axis([0, 10, 0, 10])
ax.text(3, 8, 'boxed italics text in data coords', style='italic',
bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})
ax.text(2, 6, r'an equation: $E=mc^2$', fontsize=15)
ax.text(3, 2, 'Unicode: Institut für Festkörperphysik')
ax.text(0.95, 0.01, 'colored text in axes coords',
verticalalignment='bottom', horizontalalignment='right',
transform=ax.transAxes,
color='green', fontsize=15)
ax.plot([2], [1], 'o')
ax.annotate('annotate', xy=(2, 1), xytext=(3, 4),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.show()
x 轴和 y 轴的标签#
通过 set_xlabel
和 set_ylabel
方法,可以轻松地指定 x 轴和 y 轴的标签。
import matplotlib.pyplot as plt
import numpy as np
x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Damped oscillation [V]')
plt.show()
x 轴和 y 轴标签会自动放置,以避免与 x 轴和 y 轴刻度标签重叠。比较下面的绘图和上面的绘图,注意 y 轴标签位于上面标签的左侧。
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1*10000)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Damped oscillation [V]')
plt.show()
如果要移动标签,可以指定 labelpad 关键字参数,其值以点 (1/72") 为单位(与指定字体大小相同的单位)。
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1*10000)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Damped oscillation [V]', labelpad=18)
plt.show()
或者,标签接受所有 Text
关键字参数,包括 position,通过它可以手动指定标签位置。这里我们将 x 轴标签放在轴的最左侧。注意,此位置的 y 坐标没有影响 - 要调整 y 位置,需要使用 labelpad 关键字参数。
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('Time [s]', position=(0., 1e6), horizontalalignment='left')
ax.set_ylabel('Damped oscillation [V]')
plt.show()
本教程中的所有标签都可以通过操作 matplotlib.font_manager.FontProperties
方法,或通过 set_xlabel
的命名关键字参数进行更改。
from matplotlib.font_manager import FontProperties
font = FontProperties()
font.set_family('serif')
font.set_name('Times New Roman')
font.set_style('italic')
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('Time [s]', fontsize='large', fontweight='bold')
ax.set_ylabel('Damped oscillation [V]', fontproperties=font)
plt.show()
最后,我们可以在所有文本对象中使用原生 TeX 渲染,并且可以拥有多行
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.2, left=0.2)
ax.plot(x1, np.cumsum(y1**2))
ax.set_xlabel('Time [s] \n This was a long experiment')
ax.set_ylabel(r'$\int\ Y^2\ dt\ \ [V^2 s]$')
plt.show()
标题#
子图标题的设置方式与标签非常相似,但有一个loc关键字参数可以更改位置和对齐方式,默认值为loc=center
。
标题的垂直间距由rcParams["axes.titlepad"]
(默认值:6.0
)控制。将其设置为不同的值会移动标题。
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(top=0.8)
ax.plot(x1, y1)
ax.set_title('Vertically offset title', pad=30)
plt.show()
刻度和刻度标签#
放置刻度和刻度标签是制作图形中非常棘手的一方面。Matplotlib 会尽力自动完成此任务,但它也提供了一个非常灵活的框架来确定刻度位置的选择以及如何对其进行标记。
术语#
轴具有一个matplotlib.axis.Axis
对象,用于ax.xaxis
和ax.yaxis
,其中包含有关轴中标签布局方式的信息。
轴 API 在axis
的文档中进行了详细说明。
轴对象具有主刻度和次刻度。轴具有 Axis.set_major_locator
和 Axis.set_minor_locator
方法,这些方法使用正在绘制的数据来确定主刻度和次刻度的位置。还有 Axis.set_major_formatter
和 Axis.set_minor_formatter
方法来格式化刻度标签。
简单刻度#
通常,简单地定义刻度值,有时还定义刻度标签,覆盖默认的定位器和格式化器,会很方便。但是,这样做不建议,因为它会破坏绘图的交互式导航。它还会重置轴限制:请注意,第二个绘图具有我们要求的刻度,包括那些远远超出自动视图限制的刻度。
当然,我们可以在事后修复这个问题,但这确实突出了硬编码刻度的弱点。此示例还更改了刻度的格式。
fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
# list comprehension to get all tick labels...
tickla = [f'{tick:1.2f}' for tick in ticks]
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_ticklabels(tickla)
axs[1].set_xlim(axs[0].get_xlim())
plt.show()
刻度定位器和格式化器#
与其列出所有刻度标签,我们也可以使用 matplotlib.ticker.StrMethodFormatter
(新式 str.format()
格式字符串)或 matplotlib.ticker.FormatStrFormatter
(旧式 '%' 格式字符串),并将它传递给 ax.xaxis
。一个 matplotlib.ticker.StrMethodFormatter
也可以通过传递一个 str
来创建,而无需显式创建格式化器。
当然,我们也可以使用非默认定位器来设置刻度位置。请注意,我们仍然传入刻度值,但上面使用的 x 限制修复是 *不* 需要的。
默认格式化器是 matplotlib.ticker.MaxNLocator
,调用方式为 ticker.MaxNLocator(self, nbins='auto', steps=[1, 2, 2.5, 5, 10])
。steps 关键字包含一个可用于刻度值的倍数列表。例如,在本例中,2、4、6 是可接受的刻度,20、40、60 或 0.2、0.4、0.6 也是可接受的。但是,3、6、9 是不可接受的,因为 3 不出现在步骤列表中。
nbins=auto
使用一种算法来确定根据轴的长度,多少个刻度是可接受的。刻度标签的字体大小会被考虑在内,但刻度字符串的长度不会(因为还不知道)。在底部的行中,刻度标签相当大,因此我们将 nbins
设置为 4,以使标签适合右边的图。
fig, axs = plt.subplots(2, 2, figsize=(8, 5), tight_layout=True)
for n, ax in enumerate(axs.flat):
ax.plot(x1*10., y1)
formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
locator = matplotlib.ticker.MaxNLocator(nbins='auto', steps=[1, 4, 10])
axs[0, 1].xaxis.set_major_locator(locator)
axs[0, 1].xaxis.set_major_formatter(formatter)
formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.AutoLocator()
axs[1, 0].xaxis.set_major_formatter(formatter)
axs[1, 0].xaxis.set_major_locator(locator)
formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.MaxNLocator(nbins=4)
axs[1, 1].xaxis.set_major_formatter(formatter)
axs[1, 1].xaxis.set_major_locator(locator)
plt.show()
最后,我们可以使用 matplotlib.ticker.FuncFormatter
为格式化器指定函数。此外,与 matplotlib.ticker.StrMethodFormatter
一样,传递一个函数会自动创建一个 matplotlib.ticker.FuncFormatter
。
def formatoddticks(x, pos):
"""Format odd tick positions."""
if x % 2:
return f'{x:1.2f}'
else:
return ''
fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.plot(x1, y1)
locator = matplotlib.ticker.MaxNLocator(nbins=6)
ax.xaxis.set_major_formatter(formatoddticks)
ax.xaxis.set_major_locator(locator)
plt.show()
日期刻度#
Matplotlib 可以接受 datetime.datetime
和 numpy.datetime64
对象作为绘图参数。日期和时间需要特殊的格式化,这通常需要手动干预。为了帮助您,日期有特殊的定位器和格式化器,定义在 matplotlib.dates
模块中。
一个简单的例子如下。请注意,我们必须旋转刻度标签,以防止它们相互覆盖。
import datetime
fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
base = datetime.datetime(2017, 1, 1, 0, 0, 1)
time = [base + datetime.timedelta(days=x) for x in range(len(x1))]
ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
我们可以将格式传递给 matplotlib.dates.DateFormatter
。还要注意,29 日和下个月非常接近。我们可以使用 dates.DayLocator
类来解决这个问题,它允许我们指定要使用的月份中的日期列表。类似的格式化器在 matplotlib.dates
模块中列出。
import matplotlib.dates as mdates
locator = mdates.DayLocator(bymonthday=[1, 15])
formatter = mdates.DateFormatter('%b %d')
fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
图例和注释#
脚本总运行时间:(0 分钟 6.836 秒)