用matpltolib绘图时,对于一般的需求只需要找到一个例程改一下就可以了,但是当想要把matplotlib绘图显示在GUI上时发现还是有一些基础的东西需要回过头学习一下。
首先参考官方教程:https://matplotlib.org/tutorials/introductory/usage.html#sphx-glr-tutorials-introductory-usage-py
中文参考手册:https://www.matplotlib.org.cn/tutorials/introductory/usage.html#general-concepts
对其中的使用指南Usage Guide翻译如下:
使用指南
本教程介绍了一些基本的用法模式和最佳实践,以帮助您开始使用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,但是一个给定的 对象只能位于一个。轴包含两个(注意3个轴和Axis之间的区别)的 对象(注意3个轴和Axis之间的区别),这些对象负责数据限制(也可以通过和 方法通过设置来控制数据限制 )。每个都有一个标题(通过设置 ),一个x标签(通过设置)和一个y 标签(通过 设置 )。Axes
Figure
Axis
set_xlim()
set_ylim()
Axes
Axes
set_title()
set_xlabel()
set_ylabel()
的Axes
类和它的成员函数是主要的入口点与OO接口工作。
#Axis
这些是类似数字线的对象。他们负责设置图形限制并生成刻度(轴上的标记)和刻度标签(标记刻度的字符串)。刻度的位置由对象确定,刻度 标签字符串由格式化。正确和正确的组合可以很好地控制刻度线的位置和标签。Locator
Formatter
Locator
Formatter
#Artist
基本上你可以在图中看到的一切是一个艺术家(甚至 Figure
,Axes
和Axis
对象)。这包括Text
对象,Line2D
对象, collection
对象,Patch
对象...(您明白了)。绘制图形后,所有艺术家都被绘制到画布上。大多数艺术家都被绑在斧头上。这样的艺术家不能被多个轴共享,也不能从一个轴移动到另一个轴。
#绘图功能的输入类型
所有绘图功能均预期np.array
或np.ma.masked_array
作为输入。类似于“数组”的类(例如数据对象),可能会或可能不会按预期工作。最好在绘制之前将它们转换为对象。pandas
np.matrix
np.array
例如,将 pandas.DataFrame
a = pandas.DataFrame(np.random.rand(4,5), columns = list('abcde'))
a_asarray = a.values
并转换一个 np.matrix
b = np.matrix([[1,2],[3,4]])
b_asarray = np.asarray(b)
#Matplotlib,pyplot和pylab:它们之间有何关系?
Matplotlib是整个软件包,是Matplotlib中的模块。matplotlib.pyplot
对于pyplot模块中的功能,始终有一个“当前”图形和轴(根据要求自动创建)。例如,在下面的例子中,在第一次调用plt.plot
创建轴,则后续调用plt.plot
在同一坐标添加额外的线,以及plt.xlabel
,plt.ylabel
,plt.title
和plt.legend
设置轴标签和标题和添加的图例。
x = np.linspace(0, 2, 100)
plt.plot(x, x, label='linear')
plt.plot(x, x**2, label='quadratic')
plt.plot(x, x**3, label='cubic')
plt.xlabel('x label')
plt.ylabel('y label')
plt.title("Simple Plot")
plt.legend()
plt.show()
pylab
是一个便捷模块, 在单个名称空间中批量导入 (用于绘图)和(用于数学以及使用数组)。pylab已过时,并且由于命名空间污染而强烈不建议使用pylab。使用pyplot代替。matplotlib.pyplot
numpy
对于非交互式绘图,建议使用pyplot创建图形,然后使用OO接口进行绘图。
#编码样式
查看本文档和示例时,您会发现不同的编码样式和使用模式。这些样式完全有效,各有利弊。几乎所有示例都可以转换为另一种样式并获得相同的结果。唯一的警告是避免将自己的代码的编码样式混合在一起。
注意
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'})
或者如果您想拥有2个子图:
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从数字模拟生成后记图像,还有一些人运行Web应用程序服务器以动态提供图形。
为了支持所有这些用例,matplotlib可以针对不同的输出,这些功能中的每一个都称为后端。“前端”是用户面对的代码,即绘图代码,而“后端”则是幕后的所有艰苦工作,以制作图形。后端有两种类型:用户界面后端(用于pygtk,wxpython,tkinter,qt4或macosx;也称为“交互式后端”)和硬拷贝后端以制作图像文件(PNG,SVG,PDF,PS;也称为“非交互式后端”)。
有四种配置后端的方法。如果它们相互冲突,将使用下面列表中最后提到的方法,例如,调用 将覆盖您的中的设置。use()
matplotlibrc
注意
后端名称规范不区分大小写;例如,“ GTK3Agg”和“ gtk3agg”是等效的。
使用典型的matplotlib安装(例如从二进制安装程序或linux发行软件包安装),已经设置了一个很好的默认后端,从而允许交互式工作和脚本绘制,并输出到屏幕和/或文件,因此至少在一开始,您将不需要使用上面给出的任何方法。
但是,如果您要编写图形用户界面或Web应用程序服务器(如何在Web应用程序服务器中使用Matplotlib),或者需要更好地了解正在发生的情况,请继续阅读。为了使图形用户界面更具可定制性,matplotlib将渲染器的概念(实际执行绘图的事物)与画布(绘图所在的位置)分开。用于用户界面的规范渲染器Agg
使用Anti-Grain Geometry C ++库制作图形的栅格(像素)图像。所有的用户界面除了macosx都
可与AGG渲染,可以使用例如WXAgg
,GTK3Agg
,QT4Agg
,QT5Agg
,TkAgg
。此外,某些用户界面还支持其他渲染引擎。例如,对于GTK + 3,您还可以选择Cairo渲染(后端GTK3Cairo
)。
对于渲染引擎,还区分矢量渲染器或栅格渲染器。渲染时,矢量渲染器发出诸如“从此点到该点画一条线”之类的绘图命令,因此是无比例的,而栅格渲染器后端生成该线的像素表示,其精度取决于DPI设置。
以下是matplotlib渲染器的摘要(每个渲染器都有一个同名的后端;它们是非交互式后端,能够写入文件):
渲染器文件类型说明
AGG [ png ](https://matplotlib.org/../glossary/index.html#term-png)[ 光栅图形 ](https://matplotlib.org/../glossary/index.html#term-光栅图)-使用“ 反颗粒几何”引擎的高质量图像
PS ps eps [[[ 矢量图形 ](https://matplotlib.org/../glossary/index.html#term-vector-graphics)](https://matplotlib.org/../glossary/index。 html#term-vector-graphics)](https://matplotlib.org/../glossary/index.html#term-vector-graphics)- 后记输出
PDF [ pdf ](https://matplotlib.org/../glossary/index.html#term-pdf)矢量图形- 便携式文档格式
SVG [ svg ](https://matplotlib.org/../glossary/index.html#term-svg)矢量图形- 可缩放矢量图形
开罗 png ps pdf svg光栅图形和矢量图形-使用 开罗图形库
这里是支持的用户界面和渲染器组合;这些是交互式后端,可以显示在屏幕上,并可以使用上表中的适当渲染器将其写入文件:
后端说明
Qt5 Agg在Qt5画布中进行Agg渲染(需要PyQt5)。可以使用%matplotlib qt5在IPython中激活此后端。
Jupyter小部件中嵌入的ipympl Agg渲染。(需要ipympl)。可以使用%matplotlib ipympl在Jupyter笔记本中启用此后端。
[ GTK ](https://matplotlib.org/../glossary/index.html#term-gtk)将3Agg Agg渲染到GTK 3.x画布(需要[ PyGObject ](https://wiki.gnome.org / action / show / Projects / PyGObject)和[ pycairo ](https://www.cairographics.org/pycairo/)或[ cairocffi ](https://pythonhosted.org/cairocffi/))。可以在IPython中使用%matplotlib gtk3激活此后端。
macosx将Agg渲染到OSX中的可可画布中。可以使用%matplotlib osx在IPython中激活此后端。
Tk Agg Agg渲染到Tk画布(需要TkInter)。可以使用%matplotlib tk在IPython中激活此后端。
nbAgg将交互式图形嵌入Jupyter经典笔记本中。可以通过%matplotlib笔记本在Jupyter笔记本中启用此后端。
WebAgg在show()上将启动带有互动式人物的龙卷风服务器。
GTK3Cairo开罗渲染到GTK 3.x画布(需要PyGObject,pycairo或cairocffi)。
Qt4 Agg渲染到Qt4画布(需要PyQt4或pyside)。可以在IPython中使用%matplotlib qt4激活此后端。
WXAgg Agg渲染到wxWidgets画布(需要wxPython 4)。可以在IPython中使用%matplotlib wx激活此后端。
#ipympl
Jupyter小部件生态系统发展太快,无法直接在Matplotlib中进行支持。安装ipympl
pip install ipympl
jupyter nbextension enable --py --sys-prefix ipympl
要么
conda install ipympl -c conda-forge
有关 更多详细信息,请参见jupyter-matplotlib。
#GTK和Cairo
GTK3
后端(两者 GTK3Agg
和GTK3Cairo
)取决于Cairo(pycairo> = 1.11.0或cairocffi)。
#如何选择PyQt4或PySide?
在QT_API
环境变量可以被设置为任一pyqt
或pyside
到使用PyQt4
或PySide
分别。
由于用于绑定的默认值是PyQt4
, matplotlib
首先尝试将其导入,如果导入失败,它会尝试导入PySide
。
#什么是互动模式?
使用交互式后端(请参阅什么是后端?)允许(但本身并不需要或确保)绘图到屏幕。是否以及何时在屏幕上进行绘制,以及在屏幕上绘制图形之后脚本或Shell会话是否继续,取决于调用的函数和方法,以及确定matplotlib是否处于“交互模式”的状态变量。 ”。默认布尔值由matplotlibrc
文件设置,并且可以像其他任何配置参数一样进行自定义(请参阅使用样式表和rcParams自定义Matplotlib)。也可以通过进行设置,并且可以通过来查询其值matplotlib.interactive()
matplotlib.is_interactive()
。很少需要在绘图命令中间(无论是在脚本中还是在Shell中)打开和关闭交互模式,并且可能会造成混淆,因此在下文中,我们将假定所有绘图都是通过打开或关闭交互模式完成的。
注意
在向matplotlib版本1.0过渡时,进行了与交互相关的重大更改,尤其是的角色和行为,并在1.0.1中修复了错误。在这里,我们描述了主要交互式后端的版本1.0.1行为,但macosx的部分例外 。show()
交互模式也可以通过matplotlib.pyplot.ion()打开
和matplotlib.pyplot.ioff()
来关闭。
#互动示例
在普通的python提示符下,或者在不带任何选项的情况下调用ipython之后,请尝试以下操作:
import matplotlib.pyplot as plt
plt.ion()
plt.plot([1.6, 2.7])
# 在pycharm中运行会发现绘图窗口闪现下就没了
假设您正在运行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])
什么都没发生-或至少没有任何显示在屏幕上(除非您使用的是macosx后端,这是异常的)。要显示该图,您需要执行以下操作:
plt.show()
现在您看到了该图,但是您的终端命令行没有响应;该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.simplify
和path.simplify_threshold
参数 控制渲染性能matplotlibrc
(有关文件的更多信息,请参见 使用样式表和rcParams自定义Matplotlibmatplotlibrc
)。该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'] = 1.0
plt.plot(y)
plt.show()
Matplotlib当前默认为的简化阈值1/9
。如果要更改默认设置以使用其他值,则可以更改matplotlibrc
文件。另外,您可以创建一种用于交互式绘图的新样式(具有最大程度的简化),并可以为出版物质量绘图创建另一种样式(具有最小化的简化),并在必要时激活它们。有关如何执行这些操作的说明,请参见 使用样式表和rcParams自定义Matplotlib。
通过将线段迭代合并到单个矢量中,直到下一个线段到矢量的垂直距离(在显示坐标空间中测量)大于该path.simplify_threshold
参数,简化了工作。
注意
在版本2.1中进行了有关简化线段的更改。在2.1之前的版本中,这些参数仍将改善渲染时间,但是在2.1及更高版本中,某些类型数据的渲染时间将得到极大的改善。
#标记简化
标记也可以简化,尽管不如线段健壮。标记简化仅适用于对象(通过 属性)。无论在哪里 传递构造参数(例如 和) , 都可以使用该参数:Line2D
markevery
Line2D
matplotlib.pyplot.plot()
matplotlib.axes.Axes.plot()
markevery
plt.plot(x, y, markevery=10)
markevery参数允许进行简单的二次采样,或尝试进行均匀间隔的采样(沿x轴)。有关 更多信息,请参见 Markevery演示。
#将行分成较小的块
如果使用的是Agg后端(请参阅什么是后端?),则可以使用agg.path.chunksize
rc参数。这使您可以指定块的大小,任何大于多个顶点的线都将被拆分为多条线,每条线的agg.path.chunksize
顶点数不超过多个。(除非agg.path.chunksize
为零,否则将不进行分块。)对于某些类型的数据,将行分块为合理的大小可以大大减少渲染时间。
以下脚本将首先显示没有任何块大小限制的数据,然后显示块大小为10,000的相同数据。当数字很大时,最好看到这种差异,请尝试最大化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.logspace(1,np.log10(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'
)的位置。如果有很多数据点,这可能是非常昂贵的计算。在这种情况下,您可能需要提供一个特定的位置。
#使用快速样式
该快速样式可用于自动设置简化和拆分参数合理设置,以加快绘制大量的数据。只需运行以下命令即可使用它:
import matplotlib.style as mplstyle
mplstyle.use('fast')
它的重量很轻,因此可以与其他样式很好地配合,只要确保最后应用快速样式即可,这样其他样式就不会覆盖设置:
mplstyle.use(['dark_background', 'ggplot', 'fast'])