常见问题解答#
我看不到图形窗口#
请参阅 调试图形窗口未显示 .
为什么我有这么多刻度,和/或 为什么它们是乱序的?#
导致意外刻度行为的一个常见原因是传递字符串列表而不是数字或 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)
(Source code, png)
解决方案是将字符串列表转换为数字或 datetime 对象(通常是 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 .
保存透明图形#
savefig() 命令有一个关键字参数 transparent,如果为"True",则会在保存时使图形和轴的背景透明,但不会影响屏幕上显示的图像.
如果您需要更精细的控制,例如,您不希望完全透明,或者您也希望影响屏幕上显示的版本,则可以直接设置 alpha 属性.该图形有一个名为 patch 的 Rectangle 实例,并且轴有一个名为 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)
如果您需要所有图形元素都是透明的,则当前没有全局 alpha 设置,但是您可以在单个元素上设置 alpha 通道,例如:
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手动调整子图参数.使用自动布局机制之一:
约束布局 ( 约束布局指南 )
紧密布局 ( Tight layout guide )
自己从绘图元素的大小计算出好的值 ( 以编程方式控制子图调整 )
在多个子图中对齐我的 ylabel#
如果您有多个彼此重叠的子图,并且 y 数据的比例不同,您通常会得到在多个子图之间垂直不对齐的 ylabel,这可能不太美观.默认情况下,Matplotlib 定位 ylabel 的 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 格式化器和定位器,因为两个轴是独立的.
(Source code, 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.您的问题很有可能已经被问过:
Stackoverflow 问题,标记为 matplotlib .
如果您无法通过搜索找到问题的答案,请在您发送给 mailing list 的电子邮件中提供以下信息:
您的操作系统(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 开发人员诊断您的问题很有用.
如果您使用 pre-Meson 构建系统编译了旧版本的 Matplotlib,请改为提供:
您对
setup.py/setupext.py所做的任何更改,以下命令的输出:
rm -rf build python setup.py build
在您发送给邮件列表的第一封电子邮件中包含此信息将节省大量时间.
与在 bug 跟踪器中提交 bug 相比,您更有可能从邮件列表中获得更快的响应.大多数开发人员只是定期检查 bug 跟踪器.如果确定您的问题是一个 bug 并且无法快速解决,您可能会被要求在跟踪器中提交一个 bug,以便不会丢失该问题.