使用指南

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

import matplotlib.pyplot as plt
import numpy as np

一个简单的例子

Matplotlib将数据绘制在 Figure s(即windows、Jupyter窗口小部件等),每个小部件都可以包含一个或多个 Axes (即,可以用x-y坐标(或极坐标图中的θ-r或3D图中的x-y-z等)来指定点的区域。创建带有轴的图形的最简单方法是使用 pyplot.subplots . 然后我们可以使用 Axes.plot 要在轴上绘制一些数据:

fig, ax = plt.subplots()  # Create a figure containing a single axes.
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])  # Plot some data on the axes.
usage

出:

[<matplotlib.lines.Line2D object at 0x7fa9e4fa30b8>]

许多其他打印库或语言不需要显式创建轴。例如,在MATLAB中,可以

plot([1, 2, 3, 4], [1, 4, 2, 3])  % MATLAB plot.

得到想要的图形。

实际上,您可以在Matplotlib中执行相同的操作:对于每个 Axes 作图方法中,有一个对应的函数 matplotlib.pyplot 在“当前”轴上执行绘图的模块,如果轴(及其父图形)尚不存在,则创建这些轴。所以前面的例子可以写成

plt.plot([1, 2, 3, 4], [1, 4, 2, 3])  # Matplotlib plot.
usage

出:

[<matplotlib.lines.Line2D object at 0x7fa9fc511ba8>]

人物的一部分

现在,让我们更深入地了解Matplotlib图形的组件。

../../_images/anatomy.png

Figure

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

创建新地物的最简单方法是使用pyplot::

fig = plt.figure()  # an empty figure with no Axes
fig, ax = plt.subplots()  # a figure with a single Axes
fig, axs = plt.subplots(2, 2)  # a figure with a 2x2 grid of Axes

与图形一起创建轴很方便,但您也可以稍后添加轴,以允许更复杂的轴布局。

Axes

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

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

Axis

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

Artist

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

绘图函数的输入类型

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

例如,要转换 pandas.DataFrame ::

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

并将 numpy.matrix ::

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

面向对象接口和pyplot接口

如上所述,基本上有两种使用Matplotlib的方法:

  • 显式地创建图形和轴,并调用它们的方法(“面向对象(OO)样式”)。
  • 依靠pyplot自动创建和管理图形和轴,并使用pyplot函数进行打印。

所以我们可以做(OO风格)

x = np.linspace(0, 2, 100)

# Note that even in the OO-style, we use `.pyplot.figure` to create the figure.
fig, ax = plt.subplots()  # Create a figure and an axes.
ax.plot(x, x, label='linear')  # Plot some data on the axes.
ax.plot(x, x**2, label='quadratic')  # Plot more data on the axes...
ax.plot(x, x**3, label='cubic')  # ... and some more.
ax.set_xlabel('x label')  # Add an x-label to the axes.
ax.set_ylabel('y label')  # Add a y-label to the axes.
ax.set_title("Simple Plot")  # Add a title to the axes.
ax.legend()  # Add a legend.
Simple Plot

出:

<matplotlib.legend.Legend object at 0x7fa9bfe5f438>

或(pyplot样式)

x = np.linspace(0, 2, 100)

plt.plot(x, x, label='linear')  # Plot some data on the (implicit) axes.
plt.plot(x, x**2, label='quadratic')  # etc.
plt.plot(x, x**3, label='cubic')
plt.xlabel('x label')
plt.ylabel('y label')
plt.title("Simple Plot")
plt.legend()
Simple Plot

出:

<matplotlib.legend.Legend object at 0x7fa9c0504e80>

实际上还有第三种方法,对于在GUI应用程序中嵌入Matplotlib的情况,这会完全删除pyplot,即使对于图形创建也是如此。我们不在这里讨论;更多信息请参阅图库中相应的部分 (在图形用户界面中嵌入matplotlib

Matplotlib的文档和示例同时使用OO和pyplot方法(这两种方法同样强大),您应该可以随意使用它们中的任何一种(但是,最好选择其中一种并坚持使用,而不是混合使用它们)。一般来说,我们建议将pyplot限制为交互式打印(例如,在Jupyter笔记本中),而对于非交互式打印,我们更倾向于使用OO样式(在打算作为大型项目的一部分重用的函数和脚本中)。

注解

在旧的示例中,您可能会找到使用所谓 pylab 接口,via from pylab import * . 这个star import从pyplot和 numpy ,这样我们就可以做到:

x = linspace(0, 2, 100)
plot(x, x, label='linear')
...

更像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

然后将其用作:

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

出:

[<matplotlib.lines.Line2D object at 0x7fa9fc7c5d30>]

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

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

出:

[<matplotlib.lines.Line2D object at 0x7fa9bcdb8ac8>]

对于这些简单的例子来说,这种风格似乎有些过火,但是一旦图形稍微复杂一点,它就会得到回报。

后端

什么是后端?

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

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

选择后端

有三种配置后端的方法:

  1. 这个 rcParams["backend"] (default: 'agg') 您的 matplotlibrc 文件
  2. 这个 MPLBACKEND 环境变量
  3. 函数 matplotlib.use()

更详细的描述如下。

如果存在多个配置,则列表中的最后一个配置优先;例如调用 matplotlib.use() 将覆盖您的 matplotlibrc .

如果没有显式设置后端,Matplotlib会根据系统上可用的内容以及GUI事件循环是否已在运行来自动检测可用的后端。在Linux上,如果环境变量 DISPLAY 如果未设置,“事件循环”将标识为“headless”,这将导致回退到非交互后端(agg)。

以下是配置方法的详细说明:

  1. 设置 rcParams["backend"] (default: 'agg') 在你 matplotlibrc 文件::

    backend : qt5agg   # use pyqt5 with antigrain (agg) rendering
    

    也见 使用样式表和RCPARAM自定义Matplotlib .

  2. 设置 MPLBACKEND 环境变量:

    可以为当前shell或单个脚本设置环境变量。

    在Unix上:

    > export MPLBACKEND=qt5agg
    > python simple_plot.py
    
    > MPLBACKEND=qt5agg python simple_plot.py
    

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

    > set MPLBACKEND=qt5agg
    > python simple_plot.py
    

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

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

    import matplotlib
    matplotlib.use('qt5agg')
    

    这应该在创建任何图形之前完成;否则Matplotlib可能无法切换后端并引发ImportError。

    使用 use 如果用户要使用不同的后端,则需要更改代码。因此,您应该避免显式地调用 use 除非绝对必要。

内置后端

默认情况下,Matplotlib应该自动选择一个默认的后端,该后端允许交互式工作和从脚本打印,并输出到屏幕和/或文件,因此至少最初您不需要担心后端。最常见的例外是如果您的Python发行版没有 tkinter 而且您没有安装其他GUI工具包;这发生在某些Linux发行版上,您需要安装一个名为 python-tk (或类似的)。

但是,如果要编写图形用户界面或Web应用程序服务器 (如何在web应用服务器中使用Matplotlib 或者需要更好地了解正在发生的事情,继续阅读。为了使图形用户界面的内容更具可定制性,Matplotlib将渲染器的概念(实际绘制的内容)与画布(绘制的位置)分开。用户界面的标准呈现器是 Agg 其中使用 Anti-Grain Geometry 用C++库制作一个栅格(像素)图像的图形; Qt5AggQt4AggGTK3AggwxAggTkAggmacosx 后端。另一种呈现器基于Cairo库,由 Qt5CairoQt4Cairo 等。

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

下面是matplotlib渲染器的摘要(每个渲染器都有一个同名的后端;它们是 non-interactive backends ,能够写入文件):

渲染器 文件类型 描述
AGG PNG raster 图形——使用 Anti-Grain Geometry 发动机
PDF PDF vector 图形-- Portable Document Format
PS ps、eps vector 图形-- Postscript 输出
SVG svg vector 图形-- Scalable Vector Graphics
PGF pgf,pdf格式 vector 图形--使用 pgf
开罗 png、ps、pdf、svg rastervector 图形--使用 Cairo 类库

要使用非交互式后端保存绘图,请使用 matplotlib.pyplot.savefig('filename') 方法。

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

后端 描述
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 .

注解

内置后端的名称不区分大小写;例如,“Qt5Agg”和“Qt5Agg”是等效的。

IPMPUL

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

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

conda install ipympl -c conda-forge

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

如何选择pyqt4或pyside?

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

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

使用非内置后端

更一般地说,任何可导入的后端都可以通过使用上述任何方法进行选择。如果 name.of.the.backend 是包含后端的模块,使用 module://name.of.the.backend 作为后端名称,例如。 matplotlib.use('module://name.of.the.backend') .

什么是交互模式?

使用交互式后端(请参见 什么是后端? )允许——但本身并不要求或确保——在屏幕上绘图。是否和何时打印到屏幕,以及在屏幕上绘制绘图后脚本或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])

这将弹出一个绘图窗口。终端提示将保持活动状态,以便您可以键入其他命令,例如:

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

在大多数交互式后端上,如果您通过面向对象的界面更改图形窗口,它也将被更新。E、 g.参考 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])

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

plt.show()

Now you see the plot, but your terminal command line is unresponsive; pyplot.show() blocks the input of additional commands until you manually kill the plot window.

这有什么好处——被迫使用阻塞函数?假设您需要一个脚本来将文件的内容打印到屏幕上。你想看看情节,然后结束剧本。没有一些阻止命令,比如 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提供了两种方法,可以大大减少渲染时间,但代价是对绘图外观进行细微更改(达到可设置的公差)。可用于减少渲染时间的方法取决于正在创建的绘图类型。

直线段简化

对于具有线段的绘图(例如,典型的直线绘图、多边形轮廓等),渲染性能可以通过 rcParams["path.simplify"] (default: True) 和 rcParams["path.simplify_threshold"] (default: 0.111111111111) ,例如,可以在 matplotlibrc 文件(见) 使用样式表和RCPARAM自定义Matplotlib 有关 matplotlibrc 文件)。 rcParams["path.simplify"] (default: True) 是一个布尔值,指示线段是否完全简化。 rcParams["path.simplify_threshold"] (default: 0.111111111111) 控制线段的简化程度;阈值越高,渲染速度越快。

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

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.geomspace(10, 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'] = 1.0
plt.plot(y)
plt.show()

Matplotlib当前默认为保守的简化阈值 1/9 . 如果要更改默认设置以使用其他值,可以更改 matplotlibrc 文件。或者,您可以为交互式绘图(最大化简化)创建一种新样式,为出版物质量绘图(最小化简化)创建另一种样式,并根据需要激活它们。见 使用样式表和RCPARAM自定义Matplotlib 有关如何执行这些操作的说明。

简化是通过迭代地将线段合并为一个向量,直到下一个线段与向量的垂直距离(在显示坐标空间中测量)大于 path.simplify_threshold 参数。

注解

版本2.1中对如何简化线段进行了相关更改。在2.1之前,这些参数仍然可以提高渲染时间,但在2.1及更高版本中,某些类型的数据的渲染时间将大大提高。

标记简化

标记也可以简化,尽管不如线段坚固。标记简化仅适用于 Line2D 对象(通过 markevery 财产)。无论哪里 Line2D 传递构造参数,例如 matplotlib.pyplot.plot()matplotlib.axes.Axes.plot() , the markevery 参数可以使用:

plt.plot(x, y, markevery=10)

markevery参数允许幼稚的子采样,或尝试均匀分布(沿 x 轴)取样。见 市场演示 更多信息。

将行拆分为小块

如果您使用的是agg后端(请参见 什么是后端? ),那么你就可以利用 rcParams["agg.path.chunksize"] (default: 0) 这允许您指定块大小,并且任何顶点数大于此数的线都将被拆分为多条线,每条线的顶点数不超过 agg.path.chunksize 许多顶点。(除非 agg.path.chunksize 是零,在这种情况下没有分块。)对于某些类型的数据,将行分块到合理的大小可以大大减少渲染时间。

下面的脚本将首先显示没有任何块大小限制的数据,然后显示块大小为10000的相同数据。当图形较大时,可以最好地看到差异,尝试最大化GUI,然后与它们交互:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['path.simplify_threshold'] = 1.0

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

mpl.rcParams['agg.path.chunksize'] = 0
plt.plot(y)
plt.show()

mpl.rcParams['agg.path.chunksize'] = 10000
plt.plot(y)
plt.show()

传说

轴的默认图例行为尝试查找覆盖最少数据点的位置 (loc='best' )如果有很多数据点,这可能是一个非常昂贵的计算。在这种情况下,您可能需要提供一个特定的位置。

使用 fast 风格

这个 fast 样式可用于自动将简化和分块参数设置为合理的设置,以加速绘制大量数据。只需运行以下命令即可使用:

import matplotlib.style as mplstyle
mplstyle.use('fast')

它的重量非常轻,因此可以很好地与其他样式一起使用,只需确保最后应用快速样式,这样其他样式就不会覆盖设置:

mplstyle.use(['dark_background', 'ggplot', 'fast'])

脚本的总运行时间: (0分2.611秒)

关键词:matplotlib代码示例,codex,python plot,pyplot Gallery generated by Sphinx-Gallery