MPL-02:使用Figure与Axes坐标轴管理

本主题专门讲解Figure的设计结构与Figure对象的应用:

  1. Figure对象的创建与相关参数;
  2. Figure的坐标轴管理;

一、Figure对象创建与相关参数

1. 创建Figure对象

%matplotlib inline
import matplotlib.pyplot as plt
#coding=utf-8
import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure()
fig.show(warn=False)
<Figure size 432x288 with 0 Axes>

  有兴趣的可以跟踪pyplot模块的figure函数,可以完整看见Figure的创建过程,由FigureManager创建与管理的。
  默认情况下没有Axes,就没有图形显式。

2. 创建Figure对象的参数-figure函数参数

%matplotlib inline
import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure()
fig.show(warn=False)
<Figure size 432x288 with 0 Axes>

  pylot的figure函数声明如下:

matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True, FigureClass=<class 'matplotlib.figure.Figure'>, clear=False, **kwargs)

  num : integer or string, optional, default: None
    这是Figure的ID,类型可以是整数或者字符串,缺省值None;
    |-1)如果值为None,则创建新窗体,按照递增方式赋值一个ID作为num,并返回该Figure对象;
    |-2)如果提供num为整数,并且num表示的ID存在,则激活该Figure对象,并返回Figure对象的引用。
    |-3)如果提供num为整数,并且num表示的ID不存在,则创建新窗体,赋值ID为num,并返回该Figure对象;
    |-4)如果提供num为字符串,创建方式与整数(存在与不存在)一样,但与整数不同的是字符串num会被用来作为窗体的标题,ID就不再是整数形式。
  figsize : tuple of integers, optional, default: None
    (高度,宽度)单位为英寸,缺省值由rcParams\["figure.figsize"\] = \[6.4, 4.8\]设置
  dpi : integer, optional, default: None
    分辨率:每英寸的像素值。缺省值由rcParams\["figure.dpi"\] = 100设置.
  facecolor :
    背景颜色,可以使用元组表示,也可以使用字符表示,缺省值由rcParams\["figure.facecolor"\] = 'w'设置.
  edgecolor :
    边界颜色,可以使用元组表示,也可以使用字符表示,缺省值由rcParams\["figure.edgecolor"\] = 'w'设置.
  frameon : bool, optional, default: True
    控制是否绘制、Figure的框架。
  FigureClass : subclass of Figure
    用来创建定制的Figure对象。
  clear: bool, optional, default: False
    如果Figure存在,则清除原来的内容,当num不存在,这个参数没有用。

  注意:
    |-(1)最后一个**kwargs 参数实际说明figure函数支持matplotlib中与figure有关的所有参数。
    |-(2)由于字符的颜色很难记忆,表示颜色的能力也有限,下面我采用(r,g,b,a)格式表示颜色。

%matplotlib inline
import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure(
    num='岗位分析趋势图',
    figsize=(5.5,3.5),
    dpi=100,
    facecolor=(0,1,0,1),
    edgecolor=(1,0,0,1),
    frameon=True,
    linewidth=1         #这个参数是属于kwargs的。支持所有与figure参数有关的属性。
)
plt.plot(1,1)
fig.show(warn=False)
运行效果

  在独立窗体中显示,需要添加一行代码:

plt.show()

  运行效果如下:

独立窗体显示

  从上述输出可以看出,linewidth不在其中,这个参数通过kwargs传递给Figure构造器。除了全局属性,影响到Figure的参数的,需要从Figure构造器获取。下面是Figure构造器的声明情况:

    def __init__(self,
                 figsize=None,
                 dpi=None,
                 facecolor=None,
                 edgecolor=None,
 #=============================================
                 linewidth=0.0,
 #=============================================
                 frameon=None,
                 subplotpars=None,  # default to rc
                 tight_layout=None,  # default to rc figure.autolayout
                 constrained_layout=None,  # default to rc
                                          #figure.constrained_layout.use
                 ):

  其中还有几个属性subplotsparstight_layoutconstrained_layout等几个参数,也可以在figure函数中使用,这里只有linewidth不在全局参数中。
  注意:在figure中linewidth默认值是0。

3. 创建Figure对象的参数-全局参数

  上面使用的参数,除linewidth外,实际上都可以使用全局参数来设置,这样可以简化每次调用figure的重复劳动。这些属性很难记,可以通过查文档来获取,也可以写一个程序来获取这些属性值。
  与figure有关的参数:

#coding=utf-8
import matplotlib
for key in matplotlib.rcParams.keys():
    if 'figure' in key:
        print(key,':',matplotlib.rcParams[key])
figure.autolayout : False
figure.constrained_layout.h_pad : 0.04167
figure.constrained_layout.hspace : 0.02
figure.constrained_layout.use : False
figure.constrained_layout.w_pad : 0.04167
figure.constrained_layout.wspace : 0.02
figure.dpi : 72.0
figure.edgecolor : (1, 1, 1, 0)
figure.facecolor : (1, 1, 1, 0)
figure.figsize : [6.0, 4.0]
figure.frameon : True
figure.max_open_warning : 20
figure.subplot.bottom : 0.125
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
figure.titlesize : large
figure.titleweight : normal

  下面代码是显示与所有linewidth有关的属性的缺省值。

for key in matplotlib.rcParams.keys():
    if 'linewidth' in key:
        print(key,":",matplotlib.rcParams[key])
axes.linewidth : 0.8
boxplot.boxprops.linewidth : 1.0
boxplot.capprops.linewidth : 1.0
boxplot.flierprops.linewidth : 1.0
boxplot.meanprops.linewidth : 1.0
boxplot.medianprops.linewidth : 1.0
boxplot.whiskerprops.linewidth : 1.0
grid.linewidth : 0.8
hatch.linewidth : 1.0
lines.linewidth : 1.5
patch.linewidth : 1.0

  下面使用全局参数创建Figure对象。

import matplotlib.pyplot as plt
import matplotlib as mpl
#全局参数设置
mpl.rcParams['figure.figsize']=(5.5,3.5)
mpl.rcParams['figure.dpi']=100
mpl.rcParams['figure.facecolor']=(1,1,0,1)
mpl.rcParams['figure.edgecolor']=(1,0,1,1)
mpl.rcParams['figure.frameon']=True
#创建Figure对象
fig=plt.figure(num='岗位分析趋势图',linewidth=3)
plt.plot(1,1)
fig.show(warn=False)

plt.show() #在不需要窗体的情况下,可以不使用这种方式显示。
运行效果

二、Figure对象与坐标轴

  Figure对象提供两个函数添加坐标轴:
    |- add_axes ( *args, **kwargs ) :返回Axes对象或者子类对象。
    |- add_subplot ( *args, **kwargs ):返回axes.SubplotBase对象(也是Axes的子类)或者其他Axes的子类对象

1. 使用add_axes添加坐标轴

1.1. add_axes的核心参数*args说明:

  (1)rect : sequence of float
    新坐标参数,参数形式为\[left, bottom, width, height\] 参数为分数。

  (2)projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear', str}, optional
    坐标轴类型,使用字符串表示,缺省值是矩形线性坐标轴.

  (3)polar : boolean, optional
    是否是极坐标,True表示极坐标,等价于projection='polar'.

  (4)sharex, sharey : Axes, optional
    指定共享其他坐标轴对象的属性,包含相同的界限(limits), 刻度(ticks), 与比例(scale)

  (5)label : str
    坐标轴的标签,用来唯一标示坐标轴的ID,不用于显示。

  下面是一个例子:
  注意:其中第一个参数,不能带形式参数,是必须的参数值,用来指定坐标的区域。

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure(num='岗位分析趋势图',linewidth=1)
axes=fig.add_axes(
    [0,0,1,1],
    projection='polar',#{None, 'aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear', str}
    label='坐标轴标签'
)
fig.show(warn=False)
采用的是极坐标运行效果

  绘制一个标准坐标轴:·

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure(num='岗位分析趋势图',linewidth=1)
axes=fig.add_axes(
    [0,0,1,1],
    projection='rectilinear',#{None, 'aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear', str}
    label='坐标轴标签'
)
fig.show(warn=False)
标准坐标轴

【涨姿势时刻】请大家猜猜:'aitoff', 'hammer', 'lambert', 'mollweide'都是什么坐标!

1.2.add_axes的参数**kwargs说明:

属性 属性描述
adjustable {'box', 'datalim'}
agg_filter a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
alpha float
anchor 2-tuple of floats or {'C', 'SW', 'S', 'SE', ...}
animated bool
aspect {'auto', 'equal'} or num
autoscale_on bool
autoscalex_on bool
autoscaley_on bool
axes_locator Callable[[Axes, Renderer], Bbox]
axisbelow bool or 'line'
clip_box Bbox
clip_on bool
clip_path [(Path, Transform) | Patch\ None]
contains callable
facecolor color
fc color
figure Figure
frame_on bool
gid str
in_layout bool
label object
navigate bool
navigate_mode unknown
path_effects AbstractPathEffect
picker None or bool or float or callable
position [left, bottom, width, height] or Bbox
rasterization_zorder float or None
rasterized bool or None
sketch_params (scale: float, length: float, randomness: float)
snap bool or None
title str
transform Transform
url str
visible bool
xbound unknown
xlabel str
xlim (left: float, right: float)
xmargin float greater than -0.5
xscale {"linear", "log", "symlog", "logit", ...}
xticklabels List[str]
xticks list
ybound unknown
ylabel str
ylim (bottom: float, top: float)
ymargin float greater than -0.5
yscale {"linear", "log", "symlog", "logit", ...}
yticklabels List[str]
yticks list
zorder float

【例子-1】:指定标题(title)例子

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象

fig=plt.figure('技术趋势图')
ax1=fig.add_axes(
    [0.1,0.1,0.8,0.8],label='趋势图',projection="rectilinear",
    fc=(1,0,0,1),
    title="趋势图"
)
fig.show(warn=False)
plt.show()
有乱码的title属性效果

  其中汉字问题的解决帮办法:
    (1**)获取字体配置文件与目录;
    (2)拷贝汉字字体文件到配置下面字体库目录一般是fonts/ttf目录;
    (3)修改配置文件:
  下面是获取字体配置与存放目录代码:

import matplotlib as mpl
#获取配置文件
print(mpl.get_configdir())
print(mpl.matplotlib_fname())
/Users/yangqiang/.matplotlib
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/matplotlib/mpl-data/matplotlibrc

  下面是字体设置后的效果:


使用的是msyh.ttf字体文件效果

  下面是使用代码控制字体:(由于ipython缓冲的原因,如果没有效果,建议重启ipython notebook!)

import matplotlib.pyplot as plt
import matplotlib
#建议不要使用Figure构造器创建Figure对象
matplotlib.rcParams['font.family']='Microsoft Yahei'
fig=plt.figure('技术趋势图')
ax1=fig.add_axes(
    [0.1,0.1,0.8,0.8],label='趋势图',projection="rectilinear",
    fc=(1,0,0,1),
    title="趋势图"
)
fig.show(warn=False)
plt.show()
使用字体后刷新的效果

【例子-2】:坐标轴指定标尺(xlabel,xlim,xscale)的例子

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure('技术趋势图')
ax1=fig.add_axes(
    [0.1,0.1,0.8,0.8],
    title="趋势图",
    xlabel='x坐标',ylabel='y坐标',
    xlim=(0.2,0.6),ylim=(0.4,0.6),
    xscale='log',yscale='linear',
)
fig.show(warn=False)
plt.show()
xlabel,xlim,xscale属性效果

【例子-3】:坐标轴指定刻度(xticklabels)的例子

  当指定scale的值为一些特殊的值,下面几个属性就可能没有效果,所以下面例子设置xscale与yscale的值需要小心点。在下面例子中,把xscale指定为log模式,就不会显示刻度。

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure('技术趋势图')
ax1=fig.add_axes(
    [0.1,0.1,0.8,0.8],
    title="趋势图",
    xlabel='x坐标',ylabel='y坐标',
    xlim=(0.2,0.6),ylim=(0.4,0.6),
    xscale='log',yscale='linear',
    xticklabels=['a','b','c','d','e'],yticklabels=['A','B','C','D','E','F']
)
fig.show(warn=False)
plt.show()
xticklabels属性效果

【例子-4】使用边界(margin)的例子

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure('技术趋势图')
ax1=fig.add_axes(
    [0.1,0.1,0.8,0.8],
    title="趋势图",
    xlabel='x坐标',ylabel='y坐标',
    #xlim=(0.2,0.6),ylim=(0.4,0.6),
    xscale='log',yscale='linear',
    #xticklabels=['a','b','c'],yticklabels=['A','B','C','D','E','F'],
    ymargin=-0.4
)
fig.show(warn=False)
plt.show()
margin属性效果,注意坐标轴的正负

【例子-05】 使用刻度(xticks)的例子

import matplotlib.pyplot as plt
#建议不要使用Figure构造器创建Figure对象
fig=plt.figure('技术趋势图')
ax1=fig.add_axes(
    [0.1,0.1,0.8,0.8],
    title="趋势图",
    xlabel='x坐标',ylabel='y坐标',
    xticks=[1,2,3,4,5,6],yticks=[1,2,3],
    xticklabels=['a','b','c'],
    #yticklabels=['A','B','C','D','E','F'],
    ymargin=-0.2
)
fig.show(warn=False)
plt.show()
xticks属性效果

  坐标轴的几个属性,相互之间是有影响的,有的是相互矛盾的,大家可以根据常理理解,掌握其中矛盾的地方。

1.3. 坐标轴的删除与添加

  可以通过如下函数删除坐标轴。
    |-fig.delaxes(ax)
  也可以直接添加:
    |-fig.add_axes(ax)

  我们也可以直接使用Axes类构造坐标轴对象。其中的核心参数都与上面一样。

1.4. 使用定制构造的Axes对象

  Axes的继承结构:
    |-Artist
      |-_AxesBase
        |-Axes
  Axes的构造器定义:

class matplotlib.axes.Axes(
    fig,
    rect,
    facecolor=None,
    frameon=True,
    sharex=None, sharey=None,
    label='',
    xscale=None, yscale=None,
    **kwargs)

  上面参数的含义也是显而易见的。

#coding=utf-8
import matplotlib.pyplot as plt
fig=plt.figure('技术趋势图')
ax1=plt.Axes(
    fig,
    [0.1,0.1,0.8,0.8],
    title="趋势图",
    xlabel='x坐标',ylabel='y坐标',
    xticks=[1,2,3,4,5,6],yticks=[1,2,3],
    xticklabels=['a','b','c'],
    #yticklabels=['A','B','C','D','E','F'],
    ymargin=-0.2
)
fig.add_axes(ax1)
fig.show(warn=False)
plt.show()
使用Axes对象

2. 使用add_subplot添加坐标轴

  add_subplot函数本质与上面一样,只是提供了更加灵活的方式。
  (1)函数定义如下:
    |-add_subplot(*args, **kwargs)
  (2)调用方式如下:
    |-add_subplot(nrows, ncols, index, **kwargs)
    |-add_subplot(pos, **kwargs)
    |-add_subplot(ax),这个函数与add_axes使用方法一样

  其他参数与add_axes函数一样。下面直接使用例子说明三种调用方式:

2.1. add_subplot(nrows, ncols, index, **kwargs)调用方式

  这三个参数用来产生多个坐标轴,坐标轴个数有nrows \ast ncols;
    |-nrows:坐标轴个数的行数
    |-ncols:坐标轴个数的列数
    |-index:坐标轴的位置
  位置下标从1开始

#coding=utf-8
import matplotlib.pyplot as plt
fig=plt.figure('技术趋势图')
fig.add_subplot(2,2,1)
fig.add_subplot(2,2,2)
fig.add_subplot(2,2,3)
fig.add_subplot(2,2,4)
fig.show(warn=False)
plt.show()
多个坐标轴

2.2. add_subplot(pos, **kwargs)调用方式

  pos参数用来产生多个坐标轴,pos必须是三位数的整数, ,,;
    |-第一位数表示nrows
    |-第二位数表示ncols
    |-第三位数表示index

#coding=utf-8
import matplotlib.pyplot as plt
fig=plt.figure('技术趋势图')
fig.add_subplot(221)
fig.add_subplot(222)
fig.add_subplot(223)
fig.add_subplot(224)
fig.show(warn=False)
plt.show()
使用pos形式的参数

2.2. 坐标占多行与多列的情况

【例子-1】占两列的情况

#coding=utf-8
import matplotlib.pyplot as plt
fig=plt.figure('技术趋势图')
'''
fig.add_subplot(2,2,1)
fig.add_subplot(2,2,2)
fig.add_subplot(2,2,3)
fig.add_subplot(2,2,4)
'''
fig.add_subplot(2,1,1)
fig.add_subplot(2,2,3)
fig.add_subplot(2,2,4)
fig.show(warn=False)
plt.show()
占两列的情况

【例子-2】占两行的情况

#coding=utf-8
import matplotlib.pyplot as plt
fig=plt.figure('技术趋势图')

fig.add_subplot(1,2,1)
fig.add_subplot(2,2,2)
fig.add_subplot(2,2,4)
fig.show(warn=False)
plt.show()
占两行的情况

【例子-3】占两行,第二列的情况

#coding=utf-8
import matplotlib.pyplot as plt
fig=plt.figure('技术趋势图')

fig.add_subplot(1,2,2)
fig.add_subplot(2,2,1)
fig.add_subplot(2,2,3)
fig.show(warn=False)
plt.show()
占两行,第二列的情况

附录

  1. 本文的代码列表
    |-plt02_figure.py
    |-plt02_Axes_cls.py
    |-plt02_add_axes.py
    |-plt02_add_plot.py
  2. 下载地址:
    |-https://github.com/QiangAI/AICode/tree/master/matplot


  下一个主题开始图形绘制。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容