常见问题解答#

我看不到图形窗口#

请参阅 调试图形窗口不显示的问题

为什么我有这么多刻度,或者为什么它们是乱序的?#

刻度行为异常的一个常见原因是传递了字符串列表而不是数字或日期时间对象。当读取逗号分隔的文本文件时,这种情况很容易在不知不觉中发生。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)

源代码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"] (默认值: True), 或使用不同的格式化程序。 有关详细信息,请参阅 ticker

保存透明图形#

savefig() 命令有一个关键字参数 transparent,如果为 'True',则在保存时会使图形和坐标轴背景透明,但不会影响屏幕上显示的图像。

如果您需要更精细的控制,例如,您不想要完全透明,或者您也想影响屏幕上显示的图像,您可以直接设置 alpha 属性。图形有一个名为 patchRectangle 实例,而坐标轴有一个名为 patch 的 Rectangle 实例。您可以直接在它们上设置任何属性(facecoloredgecolorlinewidthlinestylealpha)。例如

fig = plt.figure()
fig.patch.set_alpha(0.5)
ax = fig.add_subplot(111)
ax.patch.set_alpha(0.5)

如果您需要所有图形元素都是透明的,则当前没有全局 alpha 设置,但您可以在单个元素上设置 alpha 通道,例如

ax.plot(x, y, alpha=0.5)
ax.set_xlabel('volts', alpha=0.5)

将多个图保存到一个 pdf 文件#

许多图像文件格式每个文件只能有一个图像,但某些格式支持多页文件。目前,Matplotlib 仅使用 pdf 或 pgf 后端,通过 backend_pdf.PdfPagesbackend_pgf.PdfPages 类提供 pdf 文件的多页输出。

为刻度标签留出空间#

默认情况下,Matplotlib 在子图周围使用固定的百分比边距。这可能会导致标签重叠或在图形边界处被截断。有多种方法可以解决此问题

跨多个子图对齐我的 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() 实现(目前不支持两个以上的刻度,但这在愿望清单上)。这种方法效果相当不错,但当您尝试交互式平移和缩放时,会出现一些怪异之处,因为两个刻度都无法收到信号。

该方法使用 twinx()(及其姊妹函数 twiny())来使用2 个不同的坐标轴,关闭第二个坐标轴的矩形框架,以避免遮挡第一个坐标轴,并根据需要手动设置刻度位置和标签。您可以根据需要使用单独的 matplotlib.ticker 格式化器和定位器,因为这两个坐标轴是独立的。

(源代码, 2x.png, png)

请参阅具有不同刻度的绘图 获取完整示例。

生成图像而不显示窗口#

只需不调用 show,直接将图形保存为所需的格式即可。

import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.savefig('myfig.png')

另请参阅

嵌入到 Web 应用程序服务器 (Flask) 中,了解如何在 Web 应用程序中运行 matplotlib。

使用线程#

Matplotlib 不是线程安全的:实际上,存在已知的竞争条件会影响某些艺术家。因此,如果您使用线程,您有责任设置适当的锁来序列化对 Matplotlib artist 的访问。

您或许可以在单独的线程中处理单独的图形。但是,在这种情况下,您必须使用非交互式后端(通常为 Agg),因为大多数 GUI 后端需要从主线程运行。

获取帮助#

有很多很好的资源可以帮助您使用 Matplotlib。您的问题很有可能已经被问过

如果您无法通过搜索找到问题的答案,请在发送给 邮件列表 的电子邮件中提供以下信息

  • 您的操作系统(Linux/Unix 用户:发布 uname -a 的输出)。

  • Matplotlib 版本

    python -c "import matplotlib; print(matplotlib.__version__)"
    
  • 您从哪里获取 Matplotlib(例如,您的 Linux 发行版软件包、GitHub、PyPI 或 Anaconda)。

  • 您对 matplotlibrc 文件的任何自定义设置(请参阅 使用样式表和 rcParams 自定义 Matplotlib)。

  • 如果问题可重现,请尝试提供一个最小的、独立的 Python 脚本来演示该问题。这是关键步骤。如果您无法发布一段我们可以运行并重现您的错误的代码,那么获得帮助的机会将大大减少。通常,仅仅尝试将您的代码缩小到产生错误的最小部分,就会帮助您找到的代码中导致问题的错误。

  • 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
    

在您发送给邮件列表的第一封电子邮件中包含此信息将节省大量时间。

您向邮件列表发送邮件可能会比在错误跟踪器中提交错误更快地获得响应。大多数开发人员仅定期检查错误跟踪器。如果确定您的问题是一个错误并且无法快速解决,则可能会要求您在跟踪器中提交错误,以免该问题丢失。