Matplotlib is hiring a Research Software Engineering Fellow! See discourse for details. Apply by January 3, 2020

Version 3.1.1
matplotlib
Fork me on GitHub

目录

Related Topics

使用指南

本教程介绍一些基本的使用模式和最佳实践,以帮助您开始使用matplotlib。

一般概念

matplotlib 有一个广泛的代码库,可以令许多新用户望而生畏。然而,大多数matplotlib可以用一个相当简单的概念框架和一些重要的知识点来理解。

绘图需要在一系列级别上进行操作,从最一般的(例如“轮廓此二维数组”)到最具体的(例如“将此屏幕像素涂成红色”)。绘图包的目的是帮助您尽可能容易地可视化数据,并进行所有必要的控制——也就是说,大部分时间使用相对较高级别的命令,并且在需要时仍然能够使用较低级别的命令。

因此,Matplotlib中的所有内容都是按层次组织的。层次结构顶部是matplotlib“状态机环境”,由 matplotlib.pyplot 模块。在这个级别上,简单的函数用于向当前图形中的当前轴添加绘图元素(线、图像、文本等)。

注解

Pyplot的状态机环境的行为与Matlab类似,应该对具有Matlab经验的用户最熟悉。

层次结构中的下一级是面向对象接口的第一级,其中pyplot仅用于创建图形等少数功能,用户显式创建并跟踪图形和轴对象。在这个级别上,用户使用Pyplot创建图形,通过这些图形,可以创建一个或多个轴对象。这些轴对象随后用于大多数打印操作。

对于更多的控制——这对于在GUI应用程序中嵌入Matplotlib图是必不可少的——Pyplot级别可能会完全降低,只剩下一种纯面向对象的方法。

# sphinx_gallery_thumbnail_number = 3
import matplotlib.pyplot as plt
import numpy as np

人物的一部分

使用指南

Figure

这个 整体 数字。这个数字记录了所有的孩子 Axes 少量的“特殊”艺术家(头衔、人物传说等),以及 帆布 . (不要太担心画布,它是至关重要的,因为它实际上是一个对象来绘制您的绘图,但作为用户,它或多或少对您是不可见的)。一个数字可以有任何数字 Axes 但要有用,至少要有一个。

创建新图形的最简单方法是使用Pyplot:

fig = plt.figure()  # an empty figure with no axes
fig.suptitle('No axes on this figure')  # Add a title so we know which it is

fig, ax_lst = plt.subplots(2, 2)  # a figure with a 2x2 grid of Axes
  • 使用指南
  • 使用指南

Axes

这就是你所认为的“绘图”,它是图像中带有数据空间的区域。给定的图形可以包含多个轴,但给定的 Axes 对象只能位于一个 Figure . 轴包含两个(如果是三维的,则为三个) Axis 对象(注意 AxesAxis )它负责处理数据限制(数据限制也可以通过设置通过 set_xlim()set_ylim() Axes 方法)。各 Axes 有标题(通过设置 set_title() )X标签(通过设置 set_xlabel() )和Y标签集,通过 set_ylabel()

这个 Axes 类及其成员函数是使用OO接口的主要入口点。

Axis

这些是类似数字线的对象。它们负责设置图形限制并生成记号(轴上的标记)和记号标签(标记记号的字符串)。刻度的位置由 Locator 对象和TickLabel字符串的格式由 Formatter . 正确的组合 LocatorFormatter 对刻度线位置和标签进行非常精细的控制。

Artist

基本上,你能看到的一切都是一个艺术家(甚至 FigureAxesAxis 对象)。这包括 Text 物体, Line2D 物体, collection 物体, Patch 物体。。。(你明白了)。当图形被渲染时,所有的艺术家都被绘制到 帆布 . 大多数艺术家都绑在一个轴上;这样的艺术家不能被多个轴共享,也不能从一个轴移动到另一个轴上。

绘图函数的输入类型

所有绘图功能 np.arraynp.ma.masked_array 作为输入。“array like”类,例如 pandas 数据对象和 np.matrix 可能工作,也可能不工作。最好把这些换成 np.array 打印前的对象。

例如,要转换 pandas.DataFrame ::

a = pandas.DataFrame(np.random.rand(4,5), columns = list('abcde'))
a_asndarray = a.values

隐藏一个 np.matrix ::

b = np.matrix([[1,2],[3,4]])
b_asarray = np.asarray(b)

编码风格

在查看此文档和示例时,您将发现不同的编码样式和使用模式。这些风格是完全有效的,有其利弊。几乎所有的示例都可以转换成另一种样式并获得相同的结果。唯一需要注意的是,避免为自己的代码混合编码样式。

注解

Matplotlib的开发人员必须遵循特定的风格和指南。见 Matplotlib开发者指南 .

在不同的风格中,有两种是官方支持的。因此,这些是使用matplotlib的首选方法。

对于pyplot样式,脚本顶部的导入通常为:

import matplotlib.pyplot as plt
import numpy as np

然后调用np.arange、np.zeros、np.pi、plt.figure、plt.plot、plt.show等。使用pyplot接口创建图形,然后使用其他对象方法:

x = np.arange(0, 10, 0.2)
y = np.sin(x)
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
使用指南

那么,为什么所有额外的类型都是Matlab样式(它依赖于全局状态和平面名称空间)?对于像这个例子这样的简单的事情,唯一的优势是学术性的:更冗长的风格更明确,更清楚地说明事情的来源和发生的事情。对于更复杂的应用程序,这种明确性和清晰性变得越来越有价值,更丰富和更完整的面向对象的接口可能使程序更容易编写和维护。

通常,人们会发现自己一次又一次地绘制相同的图,但是使用不同的数据集,这就需要编写专门的函数来进行绘制。建议的函数签名如下:

def my_plotter(ax, data1, data2, param_dict):
    """
    A helper function to make a graph

    Parameters
    ----------
    ax : Axes
        The axes to draw to

    data1 : array
       The x data

    data2 : array
       The y data

    param_dict : dict
       Dictionary of kwargs to pass to ax.plot

    Returns
    -------
    out : list
        list of artists added
    """
    out = ax.plot(data1, data2, **param_dict)
    return out

# which you would then use as:

data1, data2, data3, data4 = np.random.randn(4, 100)
fig, ax = plt.subplots(1, 1)
my_plotter(ax, data1, data2, {'marker': 'x'})
使用指南

或者如果你想要两个子图:

fig, (ax1, ax2) = plt.subplots(1, 2)
my_plotter(ax1, data1, data2, {'marker': 'x'})
my_plotter(ax2, data3, data4, {'marker': 'o'})
使用指南

同样,对于这些简单的例子来说,这种风格似乎是多余的,但是一旦图表变得稍微复杂一些,它就会得到回报。

后端

什么是后端?

网站和邮件列表中的很多文档都指的是“后端”,许多新用户对这个术语感到困惑。Matplotlib针对许多不同的用例和输出格式。有些人在python shell中交互地使用matplotlib,当他们输入命令时会弹出绘图窗口。有些人跑 Jupyter 笔记本和绘制内联绘图,以便快速进行数据分析。其他人将matplotlib嵌入到图形用户界面中,比如wxpython或pygtk,以构建丰富的应用程序。有些人在批处理脚本中使用matplotlib从数值模拟中生成PostScript图像,还有一些人运行Web应用服务器来动态地提供图形。

为了支持所有这些用例,matplotlib可以针对不同的输出,这些功能中的每一个都称为后端;“前端”是面向用户的代码,即绘图代码,而“后端”则在幕后完成了所有繁重的工作来生成数字。有两种后端:用户界面后端(用于pygtk、wxpython、tkinter、qt4或macosx;也称为“交互后端”)和硬拷贝后端以生成图像文件(png、svg、pdf、ps;也称为“非交互后端”)。

配置后端有四种方法。如果它们相互冲突,将使用下面列表中最后提到的方法,例如调用 use() 将覆盖您的 matplotlibrc .

  1. 这个 backend 您的 matplotlibrc 文件(见) 使用样式表和RCPARAM自定义Matplotlib ):

    backend : WXAgg   # use wxpython with antigrain (agg) rendering
    
  2. 设置 MPLBACKEND 环境变量,用于当前shell或单个脚本。在UNIX上::

    > export MPLBACKEND=module://my_backend
    > python simple_plot.py
    
    > MPLBACKEND="module://my_backend" python simple_plot.py
    

    在窗户上,只有前者是可能的:

    > set MPLBACKEND=module://my_backend
    > python simple_plot.py
    

    设置此环境变量将重写 backend 参数在 any matplotlibrc ,即使有 matplotlibrc 在当前工作目录中。因此设置 MPLBACKEND 全球范围内,例如 .bashrc.profile 不鼓励,因为这可能导致违反直觉的行为。

  3. 如果脚本依赖于特定的后端,则可以使用 use() 功能:

    import matplotlib
    matplotlib.use('PS')   # generate postscript output by default
    

    如果您使用 use() 函数,这必须在导入之前完成 matplotlib.pyplot . 打电话 use() 导入Pyplot后将不起作用。使用 use() 如果用户要使用不同的后端,则需要更改代码。因此,您应该避免显式地调用 use() 除非绝对必要。

注解

后端名称规范不区分大小写;例如,“gtk3agg”和“gtk3agg”是等效的。

对于matplotlib的典型安装,例如二进制安装程序或Linux发行包,已经设置了一个好的默认后端,允许交互式工作和脚本打印,输出到屏幕和/或文件,因此至少在最初不需要使用上述任何方法。

但是,如果要编写图形用户界面或Web应用程序服务器 (Web应用服务器中的matplotlib 或者需要更好地了解正在发生的事情,继续阅读。为了使图形用户界面的内容更具可定制性,Matplotlib将渲染器的概念(实际绘制的内容)与画布(绘制的位置)分开。用户界面的标准呈现器是 Agg 其中使用 Anti-Grain Geometry 用C++库制作一个栅格(像素)图像的图形。所有用户界面,除了 macosx 可以与agg渲染一起使用,例如, WXAggGTK3AggQT4AggQT5AggTkAgg . 此外,一些用户界面支持其他渲染引擎。例如,使用GTK+3,还可以选择cairo渲染(后端 GTK3Cairo

对于渲染引擎,还可以区分 vectorraster 渲染器。矢量图形语言发出“从这一点到这一点画一条线”这样的绘图命令,因此是无比例的,栅格后端生成一个像素表示线,其精度取决于dpi设置。

以下是Matplotlib渲染器的摘要(每个渲染器都有一个同名的备份;这些是 non-interactive backends ,能够写入文件):

渲染器 文件类型 描述
AGG png raster graphics --使用 Anti-Grain Geometry 发动机
PS ps eps vector graphics —— Postscript 输出
PDF pdf vector graphics —— Portable Document Format
SVG svg vector graphics —— Scalable Vector Graphics
Cairo png ps pdf svg raster graphicsvector graphics --使用 Cairo graphics 类库

下面是支持的用户界面和渲染器组合;这些是 交互式后端 ,能够显示到屏幕并使用上表中的适当渲染器写入文件:

后端 描述
QT5AGG 中的agg渲染 Qt5 画布(需要 PyQt5) . 这个后端可以在ipython中使用 %matplotlib qt5 .
IPMPUL 嵌入在jupyter小部件中的agg呈现。(需要IPYMPL)。此后端可以在Jupyter笔记本中启用 %matplotlib ipympl .
GTK3AGG 将agg呈现为 GTK 3.x画布(需要 PyGObject, 和 pycairocairocffi) . 这个后端可以在ipython中使用 %matplotlib gtk3 .
麦克索克斯 在OSX中将agg渲染为可可画布。这个后端可以在ipython中使用 %matplotlib osx .
TkAgg 将agg呈现为 Tk 画布(需要 TkInter) . 这个后端可以在ipython中使用 %matplotlib tk .
恩巴格 在Jupyter经典笔记本中嵌入一个交互式图形。此后端可通过以下方式在Jupyter笔记本中启用: %matplotlib notebook .
WebAgg show() 将使用交互式图形启动Tornado服务器。
GTK3CAIRO 开罗渲染到 GTK 3.x画布(需要 PyGObject, 和 pycairocairocffi) .
QT4AGG 将agg呈现为 Qt4 画布(需要 PyQt4pyside )这个后端可以在ipython中使用 %matplotlib qt4 .
WXAgg 将agg呈现为 wxWidgets 画布(需要 wxPython 4)。这个后端可以在ipython中使用 %matplotlib wx .

IPMPUL

Jupyter小部件生态系统移动太快,无法直接在Matplotlib中支持。安装IPYMPL

pip install ipympl
jupyter nbextension enable --py --sys-prefix ipympl

conda install ipympl -c conda-forge

jupyter-matplotlib 了解更多详细信息。

GTK与开罗

GTK3 后端(后端) both GTK3AggGTK3Cairo )取决于开罗(pycairo>=1.11.0或cairocfi)。

如何选择pyqt4或pyside?

这个 QT_API 环境变量可以设置为 pyqtpyside 使用 PyQt4PySide ,分别。

因为要使用的绑定的默认值是 PyQt4matplotlib 首先尝试导入,如果导入失败,则尝试导入 PySide .

什么是交互模式?

使用交互式后端(请参见 什么是后端? )允许——但本身并不要求或确保——在屏幕上绘图。是否和何时打印到屏幕,以及在屏幕上绘制绘图后脚本或shell会话是否继续,取决于调用的函数和方法,以及决定Matplotlib是否处于“交互模式”的状态变量。默认布尔值由 matplotlibrc 文件,并且可以像任何其他配置参数一样进行自定义(请参见 使用样式表和RCPARAM自定义Matplotlib )也可以通过设置 matplotlib.interactive() ,其值可以通过 matplotlib.is_interactive() . 无论是在脚本中还是在shell中,在绘图命令流的中间打开和关闭交互式模式都是很少需要的,并且可能会造成混淆,因此在下面我们将假设所有绘图都是通过打开或关闭交互式模式完成的。

注解

与交互性有关的主要变化,尤其是 show() 在向Matplotlib版本1.0的转换中进行了,并在1.0.1中修复了错误。在这里,我们描述了主交互后端的1.0.1版本的行为,除了 麦克索克斯 .

交互模式也可以通过 matplotlib.pyplot.ion() ,并通过关闭 matplotlib.pyplot.ioff() .

注解

交互模式在ipython和普通的python shell中使用合适的后端,但它确实可以 not 在空闲的IDE中工作。如果默认后端不支持交互,则可以使用中讨论的任何方法显式激活交互后端。 What is a backend? .

交互式示例

在普通的python提示下,或者在无选项地调用ipython之后,尝试以下操作:

import matplotlib.pyplot as plt
plt.ion()
plt.plot([1.6, 2.7])

假设您运行的是1.0.1或更高版本,并且默认情况下已安装并选择了交互式后端,则应看到绘图,并且终端提示也应处于活动状态;您可以键入其他命令,例如:

plt.title("interactive test")
plt.xlabel("index")

在每一行之后,你会看到图被更新。从1.5版开始,通过其他方式修改绘图 应该 也会自动更新大多数后端的显示。获取对 Axes 实例,并调用该实例的方法:

ax = plt.gca()
ax.plot([3.1, 2.2])

如果你使用某些后端(比如 macosx 或者Matplotlib的旧版本,您可能不会立即看到添加到绘图中的新行。在这种情况下,需要显式调用 draw() 为了更新绘图:

plt.draw()

非交互式示例

像前一个示例中那样启动一个新会话,但现在关闭交互式模式:

import matplotlib.pyplot as plt
plt.ioff()
plt.plot([1.6, 2.7])

没有发生任何事情——或者至少没有任何事情显示在屏幕上(除非您正在使用 麦克索克斯 后端,这是异常的)。要使绘图显示,您需要执行以下操作:

现在您看到了绘图,但是您的终端命令行没有响应;该 show() 命令 阻碍 输入附加命令,直到手动终止绘图窗口。

这有什么好处——被迫使用阻塞函数?假设您需要一个将文件内容绘制到屏幕上的脚本。你想看那个情节,然后结束脚本。如果没有诸如show()之类的阻塞命令,脚本将刷新绘图,然后立即结束,在屏幕上什么也不留下。

此外,非交互模式会延迟所有绘图,直到调用show();这比每次脚本中的一行添加新功能时重新绘制绘图更有效。

在版本1.0之前,通常不能在单个脚本中多次调用show()(尽管有时可以摆脱它);对于版本1.0.1及更高版本,取消了此限制,因此可以编写这样的脚本:

import numpy as np
import matplotlib.pyplot as plt

plt.ioff()
for i in range(3):
    plt.plot(np.random.rand(10))
    plt.show()

这就形成了三个情节,一次一个。也就是说,一旦第一个图关闭,第二个图就会出现。

总结

在交互模式下,Pyplot函数自动绘制到屏幕上。

以交互方式打印时,如果除Pyplot函数外使用对象方法调用,则调用 draw() 无论何时刷新绘图。

在脚本中使用非交互模式,在脚本中,您希望生成一个或多个图形并在结束或生成新的图形集之前显示它们。在这种情况下,使用 show() 显示图形并阻止执行,直到手动销毁它们。

性能

无论是以交互模式浏览数据还是以编程方式保存大量绘图,渲染性能都可能是管道中的一个痛苦瓶颈。Matplotlib提供了两种方法,可以大大减少渲染时间,但代价是对绘图外观进行细微更改(达到可设置的公差)。可用于减少渲染时间的方法取决于正在创建的绘图类型。

直线段简化

对于具有线段的绘图(例如典型的线图、多边形轮廓等),渲染性能可以由 path.simplifypath.simplify_threshold 您的 matplotlibrc 文件(见) 使用样式表和RCPARAM自定义Matplotlib 有关 matplotlibrc 文件)。这个 path.simplify 参数是一个布尔值,指示是否简化线段。这个 path.simplify_threshold 参数控制简化了多少线段;较高的阈值会导致更快的渲染。

下面的脚本将首先显示数据而不进行任何简化,然后通过简化显示相同的数据。试着和他们两个交流:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

# Setup, and create the data to plot
y = np.random.rand(100000)
y[50000:] *= 2
y[np.logspace(1, np.log10(50000), 400).astype(int)] = -1
mpl.rcParams['path.simplify'] = True

mpl.rcParams['path.simplify_threshold'] = 0.0
plt.plot(y)
plt.show()

mpl.rcParams['path.simplify_threshold'