文章目录
一. 改变 x 轴显示内容 xticks 方法再次说明 1. x 轴是数值型数据 2. 将 x 轴更改为字符串 3. 总结
二. 其他元素可视性 1. 显示网格:plt.grid() 2. plt.gca( ) 对坐标轴的操作 三. plt.rcParams 设置画图的分辨率,大小等信息 四. 图表的样式参数设置
五. 创建图形对象 六. 绘制多子图 1. add_axes():添加区域 2. subplot() 函数,它可以均等地划分画布 3. 设置多图的基本信息方式 3.1 在创建的时候直接设置 3.2 使用 pyplot 模块中的方法设置后再绘制 3.3 使用返回的区域对象设置
4. subplots() 函数详解
在最开始,我们先引入 Matplotlib 库,便于后续的操作。
from matplotlib import pyplot as plt
import numpy as np
一. 改变 x 轴显示内容 xticks 方法再次说明
第一个参数,需要一个数字列表,指示 x 轴上的记号应该指向哪里,我们向这个函数传递了一个字符串,但它并不知道如何将其转换为 x 轴上的位置。
1. x 轴是数值型数据
例如,我们使用 np.arange() 生成从 1991 年到 2020 年,30 年的日期数据。
dates = np. arange( 1991 , 2021 )
dates
随后,我们再使用 np.random.randint() 随机生成这 30 年的销量数据。
sales = np. random. randint( 50 , 500 , size= 30 )
sales
最后,我们将日期作为横坐标,销量作为纵坐标绘制销量图。
plt. plot( dates, sales)
通过上述步骤我们可以发现,对于数值型数组,绘图会自动分割。 但是,如果想按照自己的逻辑分割,注意数值型对应轴上面的数值,比如,我们可以将 x 轴的刻度进行修改,并绘制销量图。
% matplotlib inline
plt. xticks( [ 1980 , 1982 , 1993 ] )
plt. plot( dates, sales)
当前会看到 x 轴上面没有数据,其实是有数据,只不过,默认当前图形的 x 轴区间是 [1991,2021],对此,我们可以借助设置 %matplotlib notebook 移动图像来查看。
- % matplotlib notebook
plt. xticks( [ 1980 , 1982 , 1993 ] )
plt. plot( dates, sales)
如果我们想按照自己的逻辑分割,注意数值型使用的是元素本身,而不是元素的索引。 如果我们直接使用元素本身就会产生如下现象。
plt. xticks( [ 1990 , 2005 , 2010 , 2020 ] )
plt. plot( dates, sales)
因此,如果我们想 x 轴刻度每两年显示一次的话,就需要使用元素的索引进行销量图的绘制。
plt. xticks( np. arange( dates. min ( ) , dates. max ( ) + 2 , 2 ) , rotation= 45 )
plt. plot( dates, sales)
那么,对于上述的逻辑分割,我们也是可以使用元素本身的,只不过需要一些计算。
plt. xticks( [ dates[ i] for i in range ( 0 , len ( dates) , 2 ) ] + [ 2020 ] , rotation= 45 )
plt. plot( dates, sales)
2. 将 x 轴更改为字符串
我们将从 1991 年到 2020 年,30 年的日期修改为字符串。 这里需要注意的是 xticks 第一个参数中元素不能我字符串 。
dates = np. arange( 1991 , 2021 ) . astype( np. str_)
plt. xticks( range ( 1 , len ( dates) , 2 ) , rotation= 45 )
plt. plot( dates, sales)
3. 总结
(1) 当 x 轴是数值型,会按照数值型本身作为 x 轴的坐标。 (2) 当 x 轴为字符串类型,会按照索引作为 x 轴的坐标。 具体可见如下例子:
time= np. arange( 2000 , 2020 ) . astype( np. str_)
sales = [ 109 , 150 , 172 , 260 , 273 , 333 , 347 , 393 , 402 , 446 , 466 , 481 , 499 , 504 , 513 , 563 , 815 , 900 , 930 , 961 ]
plt. xticks( range ( 0 , len ( time) , 2 ) )
plt. yticks( color= "blue" )
plt. plot( time, sales)
二. 其他元素可视性
1. 显示网格:plt.grid()
plt. grid( True , linestyle = "--" , color = "gray" , linewidth = "0.5" , axis = 'x' )
显示网格 plt.grid() 的参数有如下含义: linestyle:线型。 color:颜色。 linewidth:宽度。 axis:x,y,both,显示x/y/两者的格网。 例如,我们可以使用 np.linspace 生成从 -Π 到 Π 并且包含终止值的 256 个数据,并分别生成一个 cos 和 sin 函数。
x = np. linspace( - np. pi, np. pi, 256 , endpoint = True )
c, s = np. cos( x) , np. sin( x)
plt. plot( x, c)
plt. plot( x, s)
plt. grid( True , linestyle= "--" )
2. plt.gca( ) 对坐标轴的操作
上图中,用红色标识出的黑色边界框线在 Matplotlib 中被称为 spines,中文翻译为脊柱。 在我的理解看来,意思是这些边界框线是坐标轴区域的支柱,那么,我们最终要挪动的其实就是这四个支柱,且所有的操作均在 plt.gca( ) 中完成,gca 就是 get current axes 的意思。 接下来需要绘制图如下:
首先,我们创建 x 轴数据,使用 np.arange( ) 生成从 -50 到 50 的 x 轴数据,再创建 y 轴的数据,y 是 x 的平方,并绘制图形。
x = np. arange( - 50 , 51 )
y = x ** 2
plt. plot( x, y)
然后,我们获取当前坐标轴,通过坐标轴 spines ,确定 top,bottom,left,right(分别表示上,下,左,右)。 此时,我们需要的是坐标轴,因此,不需要右侧和上侧线条,将其颜色设置为 none。
x = np. arange( - 50 , 51 )
y = x ** 2
ax = plt. gca( )
ax. spines[ 'right' ] . set_color( "none" )
ax. spines[ 'top' ] . set_color( "none" )
plt. plot( x, y)
随后,我们在上述的基础上,分别定义 x,y,获取当前坐标轴移动下轴到指定位置,在这里,position 位置参数有三种,data , outward(向外),axes。 axes 是 0.0 - 1.0 之间的值,按轴上的比例划分。 data 表示按数值挪动,其后数字代表挪动到 Y 轴的刻度值。 最后,在设置 y 的取值范围,将两个 0 点移动到一起。
x = np. arange( - 50 , 51 )
y = x ** 2
ax = plt. gca( )
ax. spines[ 'right' ] . set_color( "none" )
ax. spines[ 'top' ] . set_color( "none" )
ax. spines[ 'left' ] . set_position( ( 'axes' , 0.5 ) )
plt. ylim( 0 , y. max ( ) )
plt. plot( x, y)
三. plt.rcParams 设置画图的分辨率,大小等信息
plt.rcParams[‘figure.figsize’] = (8.0, 4.0) 是设置 figure_size 英寸。 plt.rcParams[‘figure.dpi’] = 300 是设置分辨率。 默认的像素:[6.0,4.0],分辨率为 72,图片尺寸为 432x288。 如果指定 dpi=100,则图片尺寸为 600*400。 如果指定 dpi=300,则图片尺寸为 1800*1200。 针对上述,我们进行如下的样例演示。 (1) 分辨率为 72,图片尺寸为 432x288(默认值)。
plt. plot( )
plt. rcParams[ 'figure.figsize' ] = ( 6.0 , 4.0 )
plt. plot( )
(3) 指定 dpi=100,图片尺寸为 600*400。
plt. rcParams[ 'figure.dpi' ] = 100
plt. plot( )
将大小设置为 (3,2) 英寸(注意横纵坐标的刻度也发生了变化)。
plt. rcParams[ 'figure.figsize' ] = ( 3 , 2 )
plt. plot( )
四. 图表的样式参数设置
1. 线条样式
传入 x,y,通过 plot 画图,并设置折线颜色、透明度、折线样式和折线宽度,标记点、标记点大小、标记点边颜色、标记点边宽,网格等。
plt. plot( x, y, color= 'red' , alpha= 0.3 , linestyle= '-' , linewidth= 5 , marker= 'o' , markeredgecolor= 'r' , markersize= '20' , markeredgewidth= 10 )
(1) color:可以使用颜色的 16 进制,也可以使用线条颜色的英文,还可是使用之前的缩写。
字符 颜色 英文全称 ‘b’ 蓝色 blue ‘g’ 绿色 green ’ r ’ 红色 red ’ c ’ 青色 cyan ’ m ’ 品红 magenta ’ y ’ 黄色 yellow ’ k ’ 黑色 black ’ w ’ 白色 white
(2) alpha:0-1,透明度。 (3) linestyle:折线样式。
字符 描述 ‘-’ 实线 ‘–’ 虚线 ‘-.’ 点划线 ‘:’ 虚线
标记符号 描述 ‘.’ 点标记 ‘o’ 圆圈标记 ‘x’ 'X’标记 ‘D’ 钻石标记 ‘H’ 六角标记 ‘s’ 正方形标记 ‘+’ 加号标记
x= np. arange( 0 , 100 , 10 )
y= x ** 2
"""linewidth 设置线条粗细
label 设置线条标签
color 设置线条颜色
linestyle 设置线条形状
marker 设置线条样点标记
"""
plt. plot( x, y, linewidth = '2' , label = "test" , color= 'b' , linestyle= '--' , marker= 'H' )
plt. legend( loc= 'upper left' )
2. 线条样式缩写
我们可以设置两条曲线,第一个是红色,点划线;第二个是品红,虚线。 将他们的线条样式进行缩写。
plt. plot( [ 1 , 2 , 3 ] , [ 4 , 7 , 6 ] , 'r*-.' )
plt. plot( [ 2 , 4 , 5 ] , [ 3 , 8 , 7 ] , 'm+--' )
除此之外,我们也可以多设置几种线条样式的组合,并将他们添加到图例当中。
plt. rcParams[ 'figure.figsize' ] = ( 8 , 4 )
x= np. linspace( 0 , 10 , 100 )
plt. plot( x, x+ 0 , '-g' , label= '-g' )
plt. plot( x, x+ 1 , '--c' , label= '--c' )
plt. plot( x, x+ 2 , '-.k' , label= '-.k' )
plt. plot( x, x+ 3 , '-r' , label= '-r' )
plt. plot( x, x+ 4 , 'o' , label= 'o' )
plt. plot( x, x+ 5 , 'x' , label= 'x' )
plt. plot( x, x+ 6 , 'dr' , label= 'dr' )
plt. legend( loc= 'lower right' , framealpha= 0.5 , shadow= True , borderpad= 0.5 )
五. 创建图形对象
在 Matplotlib 中,面向对象编程的核心思想是创建图形对象(figure object)。 通过图形对象来调用其它的方法和属性,这样有助于我们更好地处理多个画布。 在这个过程中,pyplot 负责生成图形对象,并通过该对象来添加一个或多个 axes 对象(即绘图区域)。 Matplotlib 提供了 matplotlib.figure 图形类模块,它包含了创建图形对象的方法。通过调用 pyplot 模块中 figure() 函数来实例化 figure 对象。
plt. figure( num= None , figsize= None , dpi= None , facecolor= None , edgecolor= None , frameon= True , ** kwargs)
其参数具有如下含义: num 表示图像编号或名称,数字为编号,字符串为名称。 figsize 表示指定 figure 的宽和高,单位为英寸。 dpi 表示定绘图对象的分辨率,即每英寸多少个像素,缺省值为 72。 facecolor 表示背景颜色。 edgecolor 表示边框颜色。 frameon 表示是否显示边框。 具体可见如下例子。 创建图形对象,就相当于我们创建一个画布。 之前通过配置更改图形的分辨率和宽高.。现在可以在创建图像对象的时候创建。
from matplotlib import pyplot as plt
fig = plt. figure( )
fig = plt. figure( 'f1' , figsize= ( 3 , 2 ) , dpi= 100 )
x = np. arange( 0 , 50 )
y = x ** 2
plt. plot( x, y)
然后,我们创建图形对象,图形对象的分辨率为 100,背景颜色为:灰色,并获取轴。
x = np. arange( 0 , 50 )
y = x ** 2
fig = plt. figure( 'f1' , figsize= ( 4 , 2 ) , dpi= 100 , facecolor= 'gray' )
ax = plt. gca( )
ax. plot( x, y)
plt. plot( x, y)
六. 绘制多子图
figure 是绘制对象(可理解为一个空白的画布),一个 figure 对象可以包含多个 Axes 子图,一个 Axes 是一个绘图区域,不加设置时,Axes 值默认为 1,且每次绘图其实都是在 figure 上的 Axes 上绘图。 我们是在图形对象上面的 Axes 区域进行作画。 接下来我们将学习绘制子图的几种方式: (1) add_axes():添加区域。 (2) subplot():均等地划分画布,只是创建一个包含子图区域的画布,(返回区域对象)。 (3) subplots():既创建了一个包含子图区域的画布,又创建了一个 figure 图形对象(返回图形对象和区域对象)。
1. add_axes():添加区域
Matplotlib 定义了一个 axes 类(轴域类),该类的对象被称为 axes 对象(即轴域对象),它指定了一个有数值范围限制的绘图区域。在一个给定的画布(figure)中可以包含多个 axes 对象,但是同一个 axes 对象只能在一个画布中使用。 2D 绘图区域(axes)包含两个轴(axis)对象 其语法如下:
add_axes( rect)
该方法用来生成一个 axes 轴域对象,对象的位置由参数 rect 决定。 rect 是位置参数,接受一个由 4 个元素组成的浮点数列表,形如 [left, bottom, width, height] ,它表示添加到画布中的矩形区域的左下角坐标 (x, y),以及宽度和高度。 如下所示: ax1 从画布起始位置绘制,宽高和画布一致;ax2 从画布 20% 的位置开始绘制, 宽高是画布的 50%。
fig = plt. figure( figsize= ( 4 , 2 ) , facecolor= 'g' )
ax1= fig. add_axes( [ 0 , 0 , 1 , 1 ] )
ax2= fig. add_axes( [ 0.1 , 0.6 , 0.3 , 0.3 ] )
ax3= fig. add_axes( [ 0.5 , 0.6 , 0.2 , 0.3 ] )
ax1. plot( x, y)
ax2. plot( x, y)
ax3. plot( x, y)
注意:每个元素的值是画布宽度和高度的分数。即将画布的宽、高作为 1 个单位。比如,[ 0.2, 0.2, 0.5, 0.5],它代表着从画布 20% 的位置开始绘制, 宽高是画布的 50% 我们创建 ax1,和画布位置一致;ax2 从画布 40% 的位置开始绘制, 宽高是画布的 50%
fig = plt. figure( figsize= ( 4 , 2 ) , facecolor= 'g' )
x = np. arange( 0 , 50 , 2 )
y = x ** 2
ax1 = fig. add_axes( [ 0.0 , 0.0 , 1 , 1 ] )
ax1. plot( x, y)
ax2= fig. add_axes( [ 0.4 , 0.4 , 0.3 , 0.3 ] )
ax2. plot( x, y)
其中区域中基本方法的使用如下: 区域图表名称:set_title。 区域中 x 轴和 y 轴名称:set_xlabel() 和 set_ylabel()。 刻度设置:set_xticks()。 区域图表图例:legend()。
2. subplot() 函数,它可以均等地划分画布
ax = plt. subplot( nrows, ncols, index, * args, ** kwargs)
nrows 表示行。 ncols 表示列。 index 表示索引。 kwargs 表示 title/xlabel/ylabel 等。 也可以直接将几个值写到一起,例如:subplot(233)。 返回:区域对象。 nrows 与 ncols 表示要划分几行几列的子区域(nrows*nclos表示子图数量),index 的初始值为1,用来选定具体的某个子区域。 例如: subplot(233) 表示在当前画布的右上角创建一个两行三列的绘图区域(如下图所示),同时,选择在第 3 个位置绘制子图。
如果新建的子图与现有的子图重叠,那么重叠部分的子图将会被自动删除,因为它们不可以共享绘图区域。 现在创建一个子图,它表示一个有 1 行 2 列的网格的顶部图。引为这个子图将与第一个重叠,所以之前创建的图将被删除,x 可省略,默认 [0,1…,N-1] 递增。
plt. plot( [ 1 , 2 , 3 ] )
plt. subplot( 211 )
plt. plot( range ( 50 , 70 ) )
plt. subplot( 212 )
plt. plot( np. arange( 12 ) ** 2 )
- 如果不想覆盖之前的图,需要先创建画布。还可以先设置画布的大小,再通过画布创建区域。
fig = plt. figure( figsize= ( 4 , 2 ) )
fig. add_subplot( 111 )
plt. plot( range ( 20 ) )
fig. add_subplot( 221 )
plt. plot( range ( 12 ) )
3. 设置多图的基本信息方式
3.1 在创建的时候直接设置
对于 subplot 关键词赋值参数的了解,可以将光标移动到 subplot 方法上,使用快捷键 shift+tab 查看具体内容。 现在创建一个子图,它表示一个有 2 行 1 列的网格的顶部图。x 可省略,默认 [0,1…,N-1] 递增。
plt. subplot( 211 , title= "pic1" , xlabel= "x axis" )
plt. plot( range ( 50 , 70 ) )
plt. subplot( 212 , title= "pic2" , xlabel= "x axis" )
plt. plot( np. arange( 12 ) ** 2 )
发现子图标题重叠,在最后使用 plt.tight_layout()。
plt. subplot( 211 , title= "pic1" , xlabel= "x axis" )
plt. plot( range ( 50 , 70 ) )
plt. subplot( 212 , title= "pic2" , xlabel= "x axis" )
plt. plot( np. arange( 12 ) ** 2 )
plt. tight_layout( )
3.2 使用 pyplot 模块中的方法设置后再绘制
plt. subplot( 211 )
plt. title( "ax1" )
plt. plot( range ( 50 , 70 ) )
plt. subplot( 212 )
plt. title( "ax2" )
plt. plot( np. arange( 12 ) ** 2 )
plt. tight_layout( )
3.3 使用返回的区域对象设置
ax1 = plt. subplot( 211 )
ax1. set_title( "ax1" )
ax1. plot( range ( 50 , 70 ) )
ax2 = plt. subplot( 212 )
ax2. set_title( "ax2" )
ax2. plot( np. arange( 12 ) ** 2 )
plt. tight_layout( )
4. subplots() 函数详解
matplotlib.pyplot 模块提供了一个 subplots() 函数,它的使用方法和 subplot() 函数类似。其不同之处在于,subplots() 既创建了一个包含子图区域的画布,又创建了一个 figure 图形对象,而 subplot() 只是创建一个包含子图区域的画布。 subplots 的函数格式如下:
fig , ax = plt. subplots( nrows, ncols)
nrows 与 ncols 表示两个整数参数,它们指定子图所占的行数、列。 函数的返回值是一个元组,包括一个图形对象和所有的 axes 对象。其中 axes 对象的数量等于 nrows * ncols,且每个 axes 对象均可通过索引值访问(从 0 开始)。 下面我们创建了一个 2 行 2 列的子图,并在每个子图中显示 4 个不同的图像。 第一幅图像就是 (0,0),显示的是
x
2
x^{2}
x 2 ;第二幅图像就是 (0,1),显示的是
x
\sqrt{x}
x
;第三幅图像就是 (1,0),显示的是
e
x
e^{x}
e x ;第四幅图像就是 (1,1),显示的是
log
10
x
\log_{10}{x}
log 10 x 。
import matplotlib. pyplot as plt
import numpy as np
fig, axes = plt. subplots( 2 , 2 )
x = np. arange( 1 , 5 )
axes[ 0 ] [ 0 ] . plot( x, x* x)
axes[ 0 ] [ 0 ] . set_title( 'square' )
axes[ 0 ] [ 1 ] . plot( x, np. sqrt( x) )
axes[ 0 ] [ 1 ] . set_title( 'square root' )
axes[ 1 ] [ 0 ] . plot( x, np. exp( x) )
axes[ 1 ] [ 0 ] . set_title( 'exp' )
axes[ 1 ] [ 1 ] . plot( x, np. log10( x) )
axes[ 1 ] [ 1 ] . set_title( 'log' )
plt. tight_layout( )
plt. show( )