Figure对象全解析 专注于matplotlib的pyplot函数式绘图的人,可能会说:Figure有什么需要解析的,我一直使用“plt.figure()”就足够了,有时我甚至直接'plt.plot()'就行了。Figure对象有必要解析吗? Figure对象是matplotlib绘图的开始,它是连接后端的桥梁,它是绘图元素定位、布局的基础。 一切可见元素皆是Artistmpl框架的artist模块中定义了一个抽象基类,用作定义下述对象的父类:
这些对象都是Artist的子类。 Artist提供了所有mpl绘图的所有可见元素。Artist对象有两种类型:
容器类型:可以容纳、包含其它Artist对象的对象。如Figure, Axes。Figure可以包含多个Axes、Text等。Axes包含Axis,Line2D,Text等。 容器把包含在其内的对象组织为一个整体。 简单类型:是标准的、最基本的绘图元件,不能再包含其它对象,如Line2D, Text, Rectangle等。 Figure是一个顶级容器matplotlib.artist模块提供了一个 Figure 类,它是顶层的容器型Artist,它容纳所有绘图元件。 在2D平面坐标中,你应该把它看成一个矩形(Rectangle)区域。创建一个Figure也就是在画布上定义一块矩形区域。 这个矩形区域有两个最根本的用处:
第2点非常重要,它是坐标变换、其它对象尺寸设置的参考对象。 Figure默认是白色、无边框的,把它填充一个其它颜色的前景色并设置边框有助于我们理解它。 输入如下代码,创建一个有前景色和边框的Figure: from matplotlib.backends.backend_agg import FigureCanvasAggfrom matplotlib.figure import Figurefig =Figure(figsize=(6.4,4.8), dpi=100, facecolor=(239/256,239/256,239/256), edgecolor=(82/256,101/256,155/256), linewidth=10.0, frameon=True, )canvas = FigureCanvasAgg(fig)s, (width, height) = canvas.print_to_buffer() from PIL import Image #调用PILim = Image.frombytes('RGBA', (width, height), s)im.show() Figure坐标系统Figure最重要的作用是提供了一个坐标系统。如上图所示,创建Figure时,它就在画布上绘制了一块矩形区域。 该矩形定义了Figure坐标系统,矩形的左下角的坐标是(0.0, 0.0),右上角坐标是(1.0,1.0)。 当我们要将一个简单的artist放到figure中时,我们需要提供一个(x, y)坐标,x, y在[0.0, 1.0]之间,用于确定放置的位置。 from matplotlib.backends.backend_agg import FigureCanvasAggfrom matplotlib.figure import Figurefig =Figure(figsize=(6.4,4.8), dpi=100, facecolor=(239/256,239/256,239/256), edgecolor=(82/256,101/256,155/256), linewidth=10.0, frameon=True, )canvas = FigureCanvasAgg(fig)#在figure的中心添加一个文本fig.text(0.5,0.5,'fig_center') s, (width, height) = canvas.print_to_buffer() from PIL import Image im = Image.frombytes('RGBA', (width, height), s)im.show() 如果要将一个容器类的artist添加到figure中时,如,我们添加一个Axes到Figure中,我们不仅要提供定位坐标(axes的左下角在figure中的位置),还要指定子容器相对于Figure的大小,用分数表示,即把Figure的宽和长看为1,子容器是它的“0.?”。 from matplotlib.backends.backend_agg import FigureCanvasAggfrom matplotlib.figure import Figurefrom matplotlib.axes import Axesfig =Figure(figsize=(6.4,4.8), dpi=100, facecolor=(239/256,239/256,239/256), edgecolor=(82/256,101/256,155/256), linewidth=10.0, frameon=True, )canvas = FigureCanvasAgg(fig)fig.text(0.5,0.5,'fig_center')#请注意下面的axes定义ax = Axes(fig,[0.1,0.2,0.3,0.8])fig.add_axes(ax)s, (width, height) = canvas.print_to_buffer() from PIL import Image #调用PILim = Image.frombytes('RGBA', (width, height), s)im.show() 请将这张图刻在脑中 添加到figure中的axes,axes的左下角是定位坐标,宽度和高度定义了axes的尺寸。axes的定位坐标和尺寸都是相对于figue来计算的。 理解Figure的坐标定位、尺寸参照作用,比掌握Figure的众多参数设置更重要! 简单地理解后端因为Figure中一些参数、方法与后端有关,而我们一般绘图又很少需要与后端打交道,但如果后端一点都不了解,又不利于从整体上把握matplotlib的架构,所以这里用草根的语言和理解简单地介绍一下后端,记住以下几点就差不多了,中高级部分再详细讨论。
试想,你并没有直接操控计算机显示系统,你仅是在写python代码,你的代码是如何与计算机显示系统良好对接的呢?你绘制的绘图元件为什么总是能正确地在屏幕上显示出来,而没有发生位置错乱、颜色错误呢? 简单地理解:后端就是将你的代码转换为计算机图形语言,并正确地在屏幕上显示出来的后台程序块。 Figure基础参数使用Figure类的调用 class matplotlib.figure.Figure( figsize=None, dpi=None, facecolor=None, edgecolor=None, linewidth=0.0, frameon=None, subplotpars=None, tight_layout=None, constrained_layout=None) 实例化Figure类时,需要9个参数,但Figure类定义中,这些形参都提供了默认值。所以,我们可以一个参数都不提供,就会取默认参数rcParams中的设置创建一个figure实例。 前往“Python草堂”群下载该表 大部分参数的设置和用法一目了然,下面补充解释下面几个参数:
color:matplotlib的颜色,可以使用常用颜色的名称指定颜色,如'red', 'blue'等,也可以使用浮点数3元素元组表示的RGB颜色,如(0.1, 0.2, 0.5),也可以这样(239/256,239/256,239/256)。 subplotpars:是SubplotParams类的一个实例,定义子图参数。如果不提供该参数,则用rcParams['figure.subplot.*']作为子图参数。一般无需设置它,默认即可。 class matplotlib.figure.SubplotParams( left=None, bottom=None, right=None, top=None, wspace=None, hspace=None ) 要自定义Figure的subplotpars参数,先创建一个figure.SubplotParams类的实例。该类的前4个参数依次是子图(矩形区域)的“左、底、右、顶”边在Figure中的位置,浮点数。 *wspace: * float,子图之间预留空间的宽度大小,用平均axis轴线宽度的分数表示。 *hspace: * float,子图之间预留空间的高度大小,用平均axis轴线高度的分数表示。 下面是默认的rcParams['figure.subplot.*'],单位是figure的分数。 'figure.subplot.bottom': 0.11, 'figure.subplot.hspace': 0.2, 'figure.subplot.left': 0.125, 'figure.subplot.right': 0.9, 'figure.subplot.top': 0.88, 'figure.subplot.wspace': 0.2, tight_layout:布尔值,或字典。设置如何调整子图的布局。如果为False,使用subplotpars参数;如果为True,使用带有默认padding的tight_layout调整subplot参数。 tight_layout(self, renderer=None, pad=1.08, h_pad=None, w_pad=None, rect=None)
下图是设置:tight_layout = False /True 的效果比较。 from matplotlib.backends.backend_agg import FigureCanvasAggfrom matplotlib.figure import Figure,SubplotParamsfrom matplotlib.axes import Axesimport numpy as npfrom numpy import mathfig =Figure(figsize=(9.6,4.8), dpi=100, facecolor=(239/256,239/256,239/256), edgecolor=(82/256,101/256,155/256), linewidth=10.0, frameon=True, subplotpars=None, tight_layout=True, constrained_layout=None )canvas = FigureCanvasAgg(fig)ax_fca = (249/256,244/256,206/256)ax_fcb = (138/256,176/256,209/256)pl_cb = (8/256,89/256,156/256)pl_cr = (239/256,8/256,8/256)ax_a = fig.add_subplot(121,facecolor=ax_fca)ax_b = fig.add_subplot(122,facecolor=ax_fcb) x = np.arange(0, 2*math.pi, 0.001)y = np.sin(x)ax_a.plot(x, y, color=pl_cr)ax_b.plot(x, y, color=pl_cb) ax_a.plot(x, np.cos(x), color='g')ax_b.plot(x, np.cos(x), color='r') s, (width, height) = canvas.print_to_buffer() from PIL import Image im = Image.frombytes('RGBA', (width, height), s)im.show() tight_layout=True tight_layout=False 还可以提供一个字典给 tight_layout,下面是在字典中设置tight_layout的示例: from matplotlib.backends.backend_agg import FigureCanvasAggfrom matplotlib.figure import Figure,SubplotParamsfrom matplotlib.axes import Axesimport numpy as npfrom numpy import mathtl = {'pad':2.0,'h_pad':1.0,'w_pad':5.0,'rect':(0.1,0.1,0.9,0.9)}fig =Figure(figsize=(9.6,4.8), dpi=100, facecolor=(239/256,239/256,239/256), edgecolor=(82/256,101/256,155/256), linewidth=10.0, frameon=True, subplotpars=None, tight_layout=tl, constrained_layout=False )canvas = FigureCanvasAgg(fig)ax_fca = (249/256,244/256,206/256)ax_fcb = (138/256,176/256,209/256)pl_cb = (8/256,89/256,156/256)pl_cr = (239/256,8/256,8/256)ax_a = fig.add_subplot(121,facecolor=ax_fca)ax_b = fig.add_subplot(122,facecolor=ax_fcb) x = np.arange(0, 2*math.pi, 0.001)y = np.sin(x)ax_a.plot(x, y, color=pl_cr)ax_b.plot(x, y, color=pl_cb) ax_a.plot(x, np.cos(x), color='g')ax_b.plot(x, np.cos(x), color='r') s, (width, height) = canvas.print_to_buffer() from PIL import Image im = Image.frombytes('RGBA', (width, height), s)im.show() 为 有意将tight_layout的一些参数设置得很夸张,以突出效果: 请与上面的图比较 constrained_layout:布尔值,如果'True',使用约束布局来调整绘图元素的位置。类似 tight_layout, 但设计得更加灵活。中级篇中再详细介绍。 注意:constrained_layout=True 与 subplots_adjust 和 tight_layout 不兼容,即不能同时设置为True。 下一篇将详细讨论figure的方法和属性。 |
|
来自: 星光闪亮图书馆 > 《Python学习》