注解
Click here 下载完整的示例代码
使用指南¶
本教程介绍一些基本的使用模式和最佳实践,以帮助您开始使用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.
出:
[<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.
出:
[<matplotlib.lines.Line2D object at 0x7fa9fc511ba8>]
人物的一部分¶
现在,让我们更深入地了解Matplotlib图形的组件。
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
对象(注意 Axes 和 Axis )它负责处理数据限制(数据限制也可以通过 axes.Axes.set_xlim()
和 axes.Axes.set_ylim()
方法)。各 Axes
有标题(通过设置 set_title()
)X标签(通过设置 set_xlabel()
)和Y标签集,通过 set_ylabel()
)
这个 Axes
类及其成员函数是使用OO接口的主要入口点。
绘图函数的输入类型¶
所有绘图功能 numpy.array
或 numpy.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.
出:
<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()
出:
<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
,这样我们就可以做到:
更像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'})
出:
[<matplotlib.lines.Line2D object at 0x7fa9fc7c5d30>]
或者如果你想要两个子图:
出:
[<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;也称为“非交互后端”)。
选择后端¶
有三种配置后端的方法:
- 这个
rcParams["backend"]
(default:'agg'
) 您的matplotlibrc
文件 - 这个
MPLBACKEND
环境变量 - 函数
matplotlib.use()
更详细的描述如下。
如果存在多个配置,则列表中的最后一个配置优先;例如调用 matplotlib.use()
将覆盖您的 matplotlibrc
.
如果没有显式设置后端,Matplotlib会根据系统上可用的内容以及GUI事件循环是否已在运行来自动检测可用的后端。在Linux上,如果环境变量 DISPLAY
如果未设置,“事件循环”将标识为“headless”,这将导致回退到非交互后端(agg)。
以下是配置方法的详细说明:
设置
rcParams["backend"]
(default:'agg'
) 在你matplotlibrc
文件::backend : qt5agg # use pyqt5 with antigrain (agg) rendering
设置
MPLBACKEND
环境变量:可以为当前shell或单个脚本设置环境变量。
在Unix上:
> export MPLBACKEND=qt5agg > python simple_plot.py > MPLBACKEND=qt5agg python simple_plot.py
在窗户上,只有前者是可能的:
> set MPLBACKEND=qt5agg > python simple_plot.py
设置此环境变量将重写
backend
参数在 anymatplotlibrc
,即使有matplotlibrc
在当前工作目录中。因此,设置MPLBACKEND
全球范围内,例如.bashrc
或.profile
不鼓励,因为这可能导致违反直觉的行为。如果脚本依赖于特定的后端,则可以使用该函数
matplotlib.use()
::import matplotlib matplotlib.use('qt5agg')
这应该在创建任何图形之前完成;否则Matplotlib可能无法切换后端并引发ImportError。
内置后端¶
默认情况下,Matplotlib应该自动选择一个默认的后端,该后端允许交互式工作和从脚本打印,并输出到屏幕和/或文件,因此至少最初您不需要担心后端。最常见的例外是如果您的Python发行版没有 tkinter
而且您没有安装其他GUI工具包;这发生在某些Linux发行版上,您需要安装一个名为 python-tk
(或类似的)。
但是,如果要编写图形用户界面或Web应用程序服务器 (如何在web应用服务器中使用Matplotlib 或者需要更好地了解正在发生的事情,继续阅读。为了使图形用户界面的内容更具可定制性,Matplotlib将渲染器的概念(实际绘制的内容)与画布(绘制的位置)分开。用户界面的标准呈现器是 Agg
其中使用 Anti-Grain Geometry 用C++库制作一个栅格(像素)图像的图形; Qt5Agg
, Qt4Agg
, GTK3Agg
, wxAgg
, TkAgg
和 macosx
后端。另一种呈现器基于Cairo库,由 Qt5Cairo
, Qt4Cairo
等。
对于渲染引擎,还可以区分 vector 或 raster 渲染器。矢量图形语言发出“从这一点到这一点画一条线”这样的绘图命令,因此是无比例的,栅格后端生成一个像素表示线,其精度取决于dpi设置。
下面是matplotlib渲染器的摘要(每个渲染器都有一个同名的后端;它们是 non-interactive backends ,能够写入文件):
渲染器 | 文件类型 | 描述 |
---|---|---|
AGG | PNG | raster 图形——使用 Anti-Grain Geometry 发动机 |
vector 图形-- Portable Document Format | ||
PS | ps、eps | vector 图形-- Postscript 输出 |
SVG | svg | vector 图形-- Scalable Vector Graphics |
PGF | pgf,pdf格式 | vector 图形--使用 pgf 包 |
开罗 | png、ps、pdf、svg | raster 或 vector 图形--使用 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, 和 pycairo 或 cairocffi) . 这个后端可以在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, 和 pycairo 或 cairocffi) . |
QT4AGG | 将agg呈现为 Qt4 画布(需要 PyQt4 或 pyside )这个后端可以在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 了解更多详细信息。
使用非内置后端¶
更一般地说,任何可导入的后端都可以通过使用上述任何方法进行选择。如果 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()
这就形成了三个情节,一次一个。也就是说,一旦第一个图关闭,第二个图就会出现。
性能¶
无论是以交互模式浏览数据还是以编程方式保存大量绘图,渲染性能都可能是管道中的一个痛苦瓶颈。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
参数可以使用:
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