常见问题#
我没有看到一个图形窗口#
请参阅 调试图形窗口不显示的问题。
为什么我有这么多勾选,和/或为什么它们顺序不对?#
导致刻度行为异常的一个常见原因是传递了一个 字符串列表而不是数字或日期时间对象 。这在读取逗号分隔的文本文件时很容易无意中发生。Matplotlib 将字符串列表视为 分类 变量(绘制分类变量),并且默认情况下为每个类别放置一个刻度,并按照它们提供的顺序绘制。
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1, 2, layout='constrained', figsize=(6, 2))
ax[0].set_title('Ticks seem out of order / misplaced')
x = ['5', '20', '1', '9'] # strings
y = [5, 20, 1, 9]
ax[0].plot(x, y, 'd')
ax[0].tick_params(axis='x', labelcolor='red', labelsize=14)
ax[1].set_title('Many ticks')
x = [str(xx) for xx in np.arange(100)] # strings
y = np.arange(100)
ax[1].plot(x, y)
ax[1].tick_params(axis='x', labelcolor='red', labelsize=14)
(Source code, 2x.png, png)
解决方案是将字符串列表转换为数字或日期时间对象(通常是 np.asarray(numeric_strings, dtype='float') 或 np.asarray(datetime_strings, dtype='datetime64[s]'))。
更多信息请参见 修复刻度过多。
确定图形中艺术家的范围#
有时我们想知道一个艺术家的范围。 Matplotlib Artist 对象有一个方法 Artist.get_window_extent,通常会返回艺术家在像素中的范围。然而,一些艺术家,特别是文本,必须在至少渲染一次后才能知道其范围。 Matplotlib 提供了 Figure.draw_without_rendering,在调用 get_window_extent 之前应该调用它。
检查图形是否为空#
空实际上可以有不同的含义。图形是否包含任何艺术家?一个带有空 Axes 的图形是否仍被视为空?如果图形渲染为纯白色(可能存在艺术家,但它们可能在绘图区域外或透明),图形是否为空?
在这里,我们将“空”定义为:“图形不包含除其背景补丁外的任何艺术家。”背景的例外是必要的,因为默认情况下,每个图形都包含一个 Rectangle 作为其背景补丁。可以通过以下方式检查此定义:
def is_empty(figure):
"""
Return whether the figure contains no Artists (other than the default
background patch).
"""
contained_artists = figure.get_children()
return len(contained_artists) <= 1
我们决定不将此作为图方法包含在内,因为这只是定义空的一种方式,而且检查上述内容仅在极少数情况下是必要的。通常,处理图的用户或程序知道他们是否已向图中添加了内容。
检查一个图形是否会呈现为空白的唯一可靠方法是实际执行这样的呈现并检查结果。
查找图形中某一类型的所有对象#
每个 Matplotlib 艺术家(参见 艺术家教程)都有一个名为 findobj() 的方法,可以用来递归搜索艺术家包含的任何艺术家,这些艺术家可能满足某些条件(例如,匹配所有 Line2D 实例或匹配某些任意的过滤函数)。例如,以下代码片段找到图形中每个具有 set_color 属性的对象,并将该对象变为蓝色:
def myfunc(x):
return hasattr(x, 'set_color')
for o in fig.findobj(myfunc):
o.set_color('blue')
你也可以按类实例进行过滤:
import matplotlib.text as text
for o in fig.findobj(text.Text):
o.set_fontstyle('italic')
防止刻度标签带有偏移#
默认的格式化程序将使用偏移量来减少刻度标签的长度。要在每个轴的基础上关闭此功能:
ax.xaxis.get_major_formatter().set_useOffset(False)
设置 rcParams["axes.formatter.useoffset"] (default: True),或使用不同的格式化器。详情请参阅 ticker。
保存透明图形#
The savefig() 命令有一个关键字参数 transparent,如果设置为 'True',将在保存时使图形和轴的背景透明,但不会影响屏幕上显示的图像。
如果你需要更精细的控制,例如,你不希望完全透明,或者你想同时影响屏幕显示的版本,你可以直接设置alpha属性。图形有一个 Rectangle 实例,称为 patch ,而轴有一个称为 patch 的Rectangle实例。你可以直接在它们上设置任何属性(facecolor,edgecolor,linewidth,linestyle,alpha)。例如:
fig = plt.figure()
fig.patch.set_alpha(0.5)
ax = fig.add_subplot(111)
ax.patch.set_alpha(0.5)
如果你需要 所有 图形元素都是透明的,目前没有全局透明度设置,但你可以为单个元素设置透明通道,例如:
ax.plot(x, y, alpha=0.5)
ax.set_xlabel('volts', alpha=0.5)
将多个图表保存到一个PDF文件中#
许多图像文件格式每个文件只能包含一张图像,但有些格式支持多页文件。目前,Matplotlib 仅通过 backend_pdf.PdfPages 和 backend_pgf.PdfPages 类,使用 pdf 或 pgf 后端,提供对 pdf 文件的多页输出。
为刻度标签腾出空间#
默认情况下,Matplotlib 在子图周围使用固定百分比的边距。这可能导致标签重叠或在图形边界处被裁剪。有多种方法可以解决这个问题:
使用
Figure.subplots_adjust/pyplot.subplots_adjust手动调整子图参数。使用其中一种自动布局机制:
根据绘图元素的大小自行计算合适的值 (以编程方式控制子图调整)
在多个子图中对齐我的y标签#
如果你有多个上下排列的子图,并且 y 数据具有不同的比例,你通常会得到不垂直对齐的 y 标签,这可能看起来不美观。默认情况下,Matplotlib 会将 y 标签的 x 位置放置在不与任何 y 刻度重叠的位置。你可以通过指定标签的坐标来覆盖此默认行为。要了解如何操作,请参阅 对齐 y 轴标签
控制绘图元素的绘制顺序#
绘图元素的绘制顺序,以及哪些元素将位于顶部,由 set_zorder 属性决定。详细描述请参见 Zorder 演示。
使图形的纵横比相等#
Axes 属性 set_aspect() 控制轴的纵横比。你可以将其设置为 'auto'、'equal' 或某个控制比例的比率:
ax = fig.add_subplot(111, aspect='equal')
参见 等轴长宽比 以获取完整示例。
绘制多个 y 轴刻度#
一个常见的需求是为左、右 y 轴设置两个刻度,这可以通过使用 twinx() 实现(虽然目前不支持两个以上的刻度,但这在愿望清单上)。这工作得相当好,尽管在尝试交互式平移和缩放时有一些小问题,因为两个刻度不会同时接收到信号。
该方法使用 twiny())来使用 2 个不同的坐标轴,在第二个坐标轴上关闭轴的矩形框架以防止遮挡第一个坐标轴,并根据需要手动设置刻度位置和标签。由于两个坐标轴是独立的,因此可以根据需要使用单独的 matplotlib.ticker 格式化器和定位器。
(Source code, 2x.png, png)
参见 不同尺度的图表 获取完整示例。
生成图像而不显示窗口#
只需不调用 show,并直接将图形保存为所需格式:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.savefig('myfig.png')
参见
嵌入到Web应用服务器(Flask)中 关于在Web应用程序中运行matplotlib的信息。
使用线程#
Matplotlib 不是线程安全的:实际上,已知某些艺术家存在竞争条件。因此,如果您使用线程工作,则您有责任设置适当的锁来序列化对 Matplotlib 艺术家的访问。
您可能能够从不同的线程处理不同的图形。然而,在这种情况下,您必须使用一个 非交互式后端 (通常是Agg),因为大多数GUI后端 需要 从主线程运行。
获取帮助#
有许多不错的资源可以帮助你解决 Matplotlib 的问题。很有可能你的问题已经被问过了:
Stackoverflow 上标记为 matplotlib 的问题。
如果您通过搜索无法找到问题的答案,请在发送到 邮件列表 的电子邮件中提供以下信息:
您的操作系统(Linux/Unix 用户:请发布
uname -a的输出)。Matplotlib 版本:
python -c "import matplotlib; print(matplotlib.__version__)"
您获取 Matplotlib 的位置(例如,您的 Linux 发行版的软件包、GitHub、PyPI 或 Anaconda)。
对
matplotlibrc文件的任何自定义设置(参见 使用样式表和rcParams自定义Matplotlib)。如果问题是可以复现的,请尝试提供一个 最小化 的独立 Python 脚本,该脚本能够展示问题。这是 关键 步骤。如果你不能提供一段我们可以运行并复现你错误的代码,获得帮助的机会将大大减少。很多时候,仅仅尝试将你的代码最小化到产生错误的最低限度,就能帮助你发现 你 代码中的一个 bug,这个 bug 正是导致问题的原因。
Matplotlib 通过
logging库提供调试信息,并提供了一个辅助函数来设置日志级别:可以调用plt.set_loglevel("info") # or "debug" for more info
获取此调试信息。
logging模块的标准函数也同样适用;例如,可以在导入 Matplotlib 之前调用 ``logging.basicConfig(level="DEBUG")``(这在获取 Matplotlib 导入期间发出的日志信息时尤其必要),或者将自定义处理程序附加到 "matplotlib" 记录器。如果你使用自定义日志配置,这可能会很有用。
如果你自己编译了 Matplotlib,请同时提供:
你的编译器版本 -- 例如,
gcc --version。输出为:
pip install --verbose
构建输出的开头包含了许多关于您平台的详细信息,这些信息对 Matplotlib 开发者诊断您的问题非常有用。
如果你使用的是Meson构建系统之前的旧版本Matplotlib,请改为提供:
你对
setup.py/setupext.py所做的任何更改,输出为:
rm -rf build python setup.py build
在您发给邮件列表的第一封电子邮件中包含这些信息将节省大量时间。
你可能会通过写邮件列表得到更快的回复,而不是在bug追踪器中提交bug。大多数开发者只是定期检查bug追踪器。如果你的问题被确定为bug且无法快速解决,你可能会被要求在追踪器中提交bug,以确保问题不会被遗漏。