常见问题#

我看不到图形窗口#

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

为什么我有如此多的刻度,和/或为什么它们乱序了?#

意外刻度行为的一个常见原因是传递字符串列表而不是数字或 datetime 对象。在读取逗号分隔的文本文件时,这很容易在不注意的情况下发生。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 仅通过 backend_pdf.PdfPagesbackend_pgf.PdfPages 类使用 pdf 或 pgf 后端向 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.pngpng

有关完整示例,请参见 具有不同刻度的绘图

在不显示窗口的情况下生成图像#

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

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

另请参见

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

使用线程#

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

你可能能够在不同的线程中处理不同的图形。但是,在这种情况下,你必须使用非交互式后端(通常是 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
    

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

您在邮件列表中获得快速回复的可能性比在缺陷跟踪器中提交缺陷的可能性更大。大多数开发人员仅定期检查缺陷跟踪器。如果您的问题已确定为缺陷并且无法快速解决,您可能会被要求在跟踪器中提交缺陷,以便问题不会丢失。