一、概述
1.matplotlib的三层api
在Matplotlib中画图的方式和现实生活中画图的方式一致。总的来说可以分成3步。
- 找一张纸或者一块画布;
- 调色等一系列前戏;
- 作画。
而在Matplotlib中,有三个对应封装的API
- matplotlib.backend_bases.FigureCanva 代表了一个绘图区,在这个绘图区上图表被绘制
- matplotlib.backend_bases.Renderer 代表了渲染器,它知道如何在绘图区上绘图。
- matplotlib.artist.Artist 代表了图表组件,它知道如何利用渲染器在绘图区上绘图。
我们通常用于有95%以上的时机都是与matplotlib.artist.Artist
类打交道,它是高层次的绘图控制。
2. Artist的分类
Artist有两种类型:primitives
和containers
。
1.
primitive
是基本要素,它包含一些我们要在绘图区作图用到的标准图形对象,如曲线Line2D,文字text,矩形Rectangle,图像image等。 2.container
是容器,即用来装基本要素的地方,包括图形figure、坐标系Axes和坐标轴Axis。他们之间的关系如下图所示【黑色字体和蓝色曲线就是基本要素,Axis、Axes、Figure都是虚拟的容器】:
3. matplotlib标准用法
matplotlib的标准使用流程为:
- 创建一个
Figure
实例- 使用
Figure
实例创建一个或者多个Axes
或Subplot
实例- 使用
Axes
实例的辅助方法来创建primitive
例:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure() #创建了一个Figure实例
ax = fig.add_subplot(2, 1, 1) #用Figure实例创建了一个两行一列(即可以有两个subplot)的绘图区
t = np.arange(0.0, 1.0, 0.01) #定义X轴
s = np.sin(2*np.pi*t) #给出Y值
line, = ax.plot(t, s, color='blue', lw=2) #画图,等同于直接 ax.plot(t,s,color='bule',lw=2)
拓展1:
fig = plt.figure() #实例化,不实例化不会直接渲染图片
ax = fig.add_subplot(2,1,1) #在画布上标注好位置
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line1 = ax.plot(t, s, color='blue', lw=2) #line1主要是方便标记自己画图放的位置
x = np.arange(0.0,1.0,0.01)
y = np.cos(2*np.pi*x)
line1 = ax.plot(x, y, color='DeepSkyBlue', lw=4) #在line1上画出第二条线
拓展2:
fig = plt.figure()
ax = fig.add_subplot(2,1,1)
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line1 = ax.plot(t, s, color='blue', lw=2)
x = np.arange(0.0,1.0,0.01)
y = np.cos(2*np.pi*x)
line1 = ax.plot(x, y, color='DeepSkyBlue', lw=4)
#上面都是拓展1的代码
ax1 = fig.add_subplot(2,1,2) #把【2,1,2】的位置给ax1
r = np.arange(0, 1, 0.001)
theta = 2 * 2*np.pi * r
line2 = ax1.plot(theta, r, color='#ee8d18', lw=3) #在Line2上画出自己的第二个图案。
二、自定义你的Artist对象
1. Artist属性
- 坐标系的属性,每次进行
plot
操作的时候,都是在坐标系中对对应点进行特定规则的渲染。 - 在图形中的每一个元素都对应着一个matplotlib
Artist
,且都有其对应的配置属性列表。 Figure
本身包含一个Rectangle,Rectangle的大小就是Figure的大小;你可以用来设置Figure的背景色和透明度。- 每个
Axes
边界框(默认白底黑边),也有一个Rectangle,通过它可以设置Axes的颜色、透明度等。 - 这些实例都存储在成员变量(member variables)
Figure.patch
和Axes.patch
中。 (Patch是一个来源于MATLAB的名词,它是图形上颜色的一个2D补丁,包含rectangels-矩形,circles-圆 和 plygons-多边形)
每个matplotlib Artist
都有以下属性:
简而言之:
- Figure.patch属性:是一个Rectangle,代表了图表的矩形框,它的大小就是图表的大小, 并且可以通过它设置figure的背景色和透明度。
Axes.patch属性:也是一个Rectangle,代表了绘图坐标轴内部的矩形框(白底黑边), 通过它可以设置Axes的颜色、透明度等。
a.Figure容器
最上层的Artist对象是Figure,它包含组成图表的所有元素
# 最上层的Artist对象是Figure,它包含组成图表的所有元素 fig = plt.figure() # 创建新的axe1 ax1 = fig.add_subplot(211) ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3]) # 位置参数,四个数分别代表了(left,bottom,width,height) print(ax1 in fig.axes and ax2 in fig.axes) #True for ax in fig.axes: # 打开所有子图的栅格显示 ax.grid(True) # 默认的坐标系统以像素点为单位,但是可以通过transform属性修改其使用的坐标系
b.Axes容器
matplotlib.axes.Axes
是matplotlib的核心。大量的用于绘图的Artist
存放在它内部,并且它有许多辅助方法来创建和添加Artist
给它自己,而且它也有许多赋值方法来访问和修改这些Artist
。和
Figure
容器类似,Axes
包含了一个patch属性,对于笛卡尔坐标系而言,它是一个Rectangle
;对于极坐标而言,它是一个Circle
。这个patch属性决定了绘图区域的形状、背景和边框。fig = plt.figure() ax = fig.add_subplot(111) ax.patch.set_facecolor('LightSteelBlue') x, y = np.random.rand(2, 100) line = ax.plot(x, y, '-', color='blue', linewidth=2)[0]
Subplot
就是一个特殊的Axes
,其实例是位于网格中某个区域的Subplot
实例。其实你也可以在任意区域创建Axes
,通过Figure.add_axes([left,bottom,width,height])
来创建一个任意区域的Axes
,其中left,bottom,width,height都是[0—1]之间的浮点数,他们代表了相对于Figure
的坐标。你不应该直接通过
Axes.lines
和Axes.patches
列表来添加图表。因为当创建或添加一个对象到图表中时,Axes
会做许多自动化的工作:它会设置Artist中figure和axes的属性,同时默认Axes的转换;
它也会检视Artist中的数据,来更新数据结构,这样数据范围和呈现方式可以根据作图范围自动调整。
你也可以使用Axes的辅助方法.add_line()
和.add_patch()
方法来直接添加。另外Axes还包含两个最重要的Artist container:
ax.xaxis
:XAxis对象的实例,用于处理x轴tick以及label的绘制ax.yaxis
:YAxis对象的实例,用于处理y轴tick以及label的绘制
会在下面章节详细说明。
- Axes容器的常见属性有:
artists
: Artist实例列表 patch
: Axes所在的矩形实例 collections
: Collection实例 images
: Axes图像 legends
: Legend 实例 lines
: Line2D 实例 patches
: Patch 实例 texts
: Text 实例 xaxis
: matplotlib.axis.XAxis 实例 yaxis
: matplotlib.axis.YAxis 实例
这里仅列举几个常见的属性,更详细的属性清单请查阅官方文档: Artist属性列表
c.Axis容器
matplotlib.axis.Axis
实例处理tick line
、grid line
、tick label
以及axis label
的绘制,它包括坐标轴上的刻度线、刻度label
、坐标网格、坐标轴标题。通常你可以独立的配置y轴的左边刻度以及右边的刻度,也可以独立地配置x轴的上边刻度以及下边的刻度。- 刻度包括主刻度和次刻度,它们都是Tick刻度对象。
Axis
也存储了用于自适应,平移以及缩放的data_interval
和view_interval
。它还有Locator实例和Formatter实例用于控制刻度线的位置以及刻度label。- 每个Axis都有一个
label
属性,也有主刻度列表和次刻度列表。这些ticks
是axis.XTick
和axis.YTick
实例,它们包含着line primitive
以及text primitive
用来渲染刻度线以及刻度文本。
刻度是动态创建的,只有在需要创建的时候才创建(比如缩放的时候)。Axis也提供了一些辅助方法来获取刻度文本、刻度线位置等等:常见的如下:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
fig, ax = plt.subplots()
x = range(0,5)
y = [2,5,7,8,10]
plt.plot(x, y, '-')
axis = ax.xaxis # axis为X轴对象
axis.get_ticklocs() # 获取刻度线位置
# array([-0.5, 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
axis.get_ticklabels() # 获取刻度label列表(一个Text实例的列表)。 可以通过minor=True|False关键字参数控制输出minor还是major的tick label。
[Text(0, 0, ''),
Text(0, 0, ''),
Text(0, 0, ''),
Text(0, 0, ''),
Text(0, 0, ''),
...
]
axis.get_ticklines() # 获取刻度线列表(一个Line2D实例的列表)。 可以通过minor=True|False关键字参数控制输出minor还是major的tick line。
#<a list of 22 Line2D ticklines objects>
axis.get_data_interval()# 获取轴刻度间隔
array([0., 4.])
axis.get_view_interval()# 获取轴视角(位置)的间隔
#array([-0.2, 4.2])
下面的例子展示了如何调整一些轴和刻度的属性(忽略美观度,仅作调整参考):
fig = plt.figure(figsize=(9,9)) # 创建一个新图表
rect = fig.patch # 矩形实例并将其设为黄色
rect.set_facecolor('lightgoldenrodyellow')
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4]) # 创一个axes对象,从(0.1,0.3)的位置开始,宽和高都为0.4,
rect = ax1.patch # ax1的矩形设为灰色
rect.set_facecolor('lightslategray')
for label in ax1.xaxis.get_ticklabels():
# 调用x轴刻度标签实例,是一个text实例
label.set_color('red') # 颜色
label.set_rotation(45) # 旋转角度
label.set_fontsize(16) # 字体大小
for line in ax1.yaxis.get_ticklines():
# 调用y轴刻度线条实例, 是一个Line2D实例
line.set_color('green') # 颜色
line.set_markersize(25) # marker大小
line.set_markeredgewidth(2)# marker粗细
plt.show()
4. Tick容器
matplotlib.axis.Tick
是从Figure
到Axes
到Axis
到Tick
中最末端的容器对象。Tick
包含了tick
、grid line
实例以及对应的label
。- 所有的这些都可以通过
Tick
的属性获取,常见的tick
属性有Tick.tick1line
:Line2D实例Tick.tick2line
:Line2D实例Tick.gridline
:Line2D实例Tick.label1
:Text实例Tick.label2
:Text实例 y轴分为左右两个,因此tick1对应左侧的轴;tick2对应右侧的轴。 x轴分为上下两个,因此tick1对应下侧的轴;tick2对应上侧的轴。
下面的例子展示了,如何将Y轴右边轴设为主轴,并将标签设置为美元符号且为绿色:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
fig, ax = plt.subplots()
ax.plot(100*np.random.rand(20))
# 设置ticker的显示格式
formatter = matplotlib.ticker.FormatStrFormatter('$%1.2f')
ax.yaxis.set_major_formatter(formatter) #设置Y轴样式
# 设置ticker的参数,右侧为主轴,颜色为绿色
ax.yaxis.set_tick_params(which='major', labelcolor='green',
labelleft=False, labelright=True)
2. 属性调用方式
Artist对象的所有属性都通过相应的 get_*
和 set_*
函数进行读写。
例如下面的语句将alpha属性设置为当前值的一半:
a = o.get_alpha()
o.set_alpha(0.5*a)
如果想一次设置多个属性,也可以用set方法:
o.set(alpha=0.5, zorder=2)
可以使用 matplotlib.artist.getp(o,"alpha")
来获取属性,如果指定属性名,则返回对象的该属性值;如果不指定属性名,则返回对象的所有的属性和值。
import matplotlib
# Figure rectangle的属性
matplotlib.artist.getp(fig.patch)
agg_filter = None alpha = None animated = False antialiased or aa = False bbox = Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0) capstyle = butt children = [] clip_box = None clip_on = True clip_path = None contains = None data_transform = BboxTransformTo( TransformedBbox( Bbox... edgecolor or ec = (1.0, 1.0, 1.0, 0.0) extents = Bbox(x0=0.0, y0=0.0, x1=432.0, y1=288.0) facecolor or fc = (1.0, 1.0, 1.0, 0.0) figure = Figure(432x288) fill = True gid = None hatch = None height = 1 in_layout = False joinstyle = miter label = linestyle or ls = solid linewidth or lw = 0.0 patch_transform = CompositeGenericTransform( BboxTransformTo( ... path = Path(array([[0., 0.], [1., 0.], [1.,... path_effects = [] picker = None rasterized = None sketch_params = None snap = None transform = CompositeGenericTransform( CompositeGenericTra... transformed_clip_path_and_affine = (None, None) url = None verts = [[ 0. 0.] [432. 0.] [432. 288.] [ 0. 288.... visible = True width = 1 window_extent = Bbox(x0=0.0, y0=0.0, x1=432.0, y1=288.0) x = 0 xy = (0, 0) y = 0 zorder = 1
三、基本元素 - primitives
现在我们知道了如何检查和设置给定对象的属性,我们还需要知道如何获取该对象。
前文介绍到,Artist
包含两种对象:基本要素-primitives
和 容器-containers
。
primitives
是基本要素,它包含一些我们要在绘图区作图用到的标准图形对象,如曲线Line2D,文本text,矩形Rectangle,图像image等。container
是容器,即用来装基本要素的地方,包括图形figure、坐标系Axes和坐标轴Axis。本章重点介绍下
primitives
的几种类型:曲线-Line2D,矩形-Rectangle,图像-image (其中文本-Text较为复杂,会在之后单独详细说明。)1. 2DLines
在matplotlib中曲线的绘制,主要是通过类
matplotlib.lines.Line2D
来完成的。
它的基类:matplotlib.artist.Artist
matplotlib中线line
的含义:它表示的可以是连接所有顶点的实线样式,也可以是每个顶点的标记。此外,这条线也会受到绘画风格的影响,比如,我们可以创建虚线种类的线。
它的构造函数:class matplotlib.lines.Line2D(xdata, ydata, linewidth=None, linestyle=None, color=None, marker=None, markersize=None, markeredgewidth=None, markeredgecolor=None, markerfacecolor=None, markerfacecoloralt='none', fillstyle=None, antialiased=None, dash_capstyle=None, solid_capstyle=None, dash_joinstyle=None, solid_joinstyle=None, pickradius=5, drawstyle=None, markevery=None, **kwargs)
其中常用的的参数有:
xdata:需要绘制的line中点的在x轴上的取值,若忽略,则默认为range(1,len(ydata)+1)
- ydata:需要绘制的line中点的在y轴上的取值
- linewidth:线条的宽度
- linestyle:线型
- color:线条的颜色
- marker:点的标记,详细可参考markers API
- markersize:标记的size
其他详细参数可参考Line2D官方文档
a. 如何设置Line2D的属性
1) 直接在plot()函数中设置
fig = plt.figure() #找画布
ax = fig.add_subplot(111) #在画布找个位置
ax.patch.set_facecolor('WhiteSmoke') #画上背景色
x = range(0,5)
y = [2,5,7,8,10]
line, = ax.plot(x,y, linewidth=10) # 画图,设置线的粗细参数为10
2) 通过获得线对象,对线对象进行设置
之前一直好奇,为什么要加line,
原来是为了后续设置line的样式哇。
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
x = range(0,5)
y = [2,5,7,8,10]
line, = ax.plot(x, y, '-')
line.set_antialiased(False) # 关闭抗锯齿功能
3) 获得线属性,使用setp()函数设置
fig = plt.figure()
ax = fig.add_subplot(111)
x = range(0,5)
lines = ax.plot(x,y,color='Cyan',linewidth=5)
# plt.setp(lines,color='Cyan',linewidth=5) 这两种写法一样,一种是直接在plot的时候设置线的类型,一种是调用setp方法设置线条类型
b. 如何绘制lines
1) 绘制直线line 常用的方法有两种
- pyplot方法绘制
- Line2D对象绘制
1. pyplot方法绘制
import matplotlib.pyplot as plt x = range(0,5) y = [2,5,7,8,10] plt.plot(x,y)
2. Line2D对象绘制
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
fig = plt.figure()
ax = fig.add_subplot(111)
line = Line2D(x, y)
ax.add_line(line)
ax.set_xlim(min(x), max(x))
ax.set_ylim(min(y), max(y))
plt.show()
2) errorbar绘制误差折线图
pyplot里有个专门绘制误差线的功能,通过errorbar
类实现,它的构造函数:
matplotlib.pyplot.errorbar(x, y, yerr=None, xerr=None, fmt=’’, ecolor=None, elinewidth=None, capsize=None, barsabove=False, lolims=False, uplims=False, xlolims=False, xuplims=False, errorevery=1, capthick=None, , data=None, *kwargs)
其中最主要的参数是前几个:
- x:需要绘制的line中点的在x轴上的取值
- y:需要绘制的line中点的在y轴上的取值
- yerr:指定y轴水平的误差
- xerr:指定x轴水平的误差
- fmt:指定折线图中某个点的颜色,形状,线条风格,例如‘co—’
- ecolor:指定error bar的颜色
- elinewidth:指定error bar的线条宽度
```python
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
x = np.arange(10)
y = 2.5 np.sin(x / 20 np.pi)
yerr = np.linspace(0,2,10)
ax1.errorbar(x, y + 3, yerr=yerr,label=’both limits (default)’) #左图
ax2 = fig.add_subplot(1,2,2) yerr = 0.2 ax2.errorbar(x, y + 3, yerr=yerr,label=’both limits ‘) # 右图
> ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2610909/1608098622529-e0598fb5-8c13-4009-a3b8-b0eafb09b9c6.png#align=left&display=inline&height=248&margin=%5Bobject%20Object%5D&name=image.png&originHeight=248&originWidth=362&size=9799&status=done&style=none&width=362)
<a name="S5NGp"></a>
## 2. patches
matplotlib.patches.Patch类是二维图形类。它的基类是matplotlib.artist.Artist,它的构造函数:<br />详细清单见 [matplotlib.patches API](https://matplotlib.org/api/patches_api.html)
> Patch(edgecolor=None, facecolor=None, color=None, linewidth=None, linestyle=None, antialiased=None, hatch=None, fill=True, capstyle=None, joinstyle=None, **kwargs)
<a name="ji0pD"></a>
### a. Rectangle-矩形
`Rectangle`矩形类在官网中的定义是: 通过锚点xy及其宽度和高度生成。 Rectangle本身的主要比较简单,即xy控制锚点,width和height分别控制宽和高。它的构造函数:
> class matplotlib.patches.Rectangle(xy, width, height, angle=0.0, **kwargs)
在实际中最常见的矩形图是hist直方图和bar条形图。<br />**1) hist-直方图**
> matplotlib.pyplot.hist(x,bins=None,range=None, density=None, bottom=None, histtype='bar', align='mid', log=False, color=None, label=None, stacked=False, normed=None)
下面是一些常用的参数:
- **x**: 数据集,最终的直方图将对数据集进行统计
- **bins**: 统计的区间分布
- **range**: tuple, 显示的区间,range在没有给出bins时生效
- **density**: bool,默认为false,显示的是频数统计结果,为True则显示频率统计结果,这里需要注意,频率统计结果=区间数目/(总数*区间宽度),和normed效果一致,官方推荐使用density
- **histtype**: 可选{'bar', 'barstacked', 'step', 'stepfilled'}之一,默认为bar,推荐使用默认配置,step使用的是梯状,stepfilled则会对梯状内部进行填充,效果与bar类似
- **align**: 可选{'left', 'mid', 'right'}之一,默认为'mid',控制柱状图的水平分布,left或者right,会有部分空白区域,推荐使用默认
- **log**: bool,默认False,即y坐标轴是否选择指数刻度
- **stacked**: bool,默认为False,是否为堆积状图
```python
import matplotlib.pyplot as plt
import numpy as np
x=np.random.randint(0,100,100) #生成【0-100】之间的100个数据,即 数据集
bins=np.arange(0,101,10) #设置连续的边界值,即直方图的分布区间[0,10],[10,20]...
plt.hist(x,bins,color='fuchsia',alpha=0.5)#alpha设置透明度,0为完全透明
plt.xlabel('scores')
plt.ylabel('count')
plt.xlim(0,100)#设置x轴分布范围 plt.show()
用Rectangle
矩形类绘制直方图
df = pd.DataFrame(columns= ['data'])
df['data'] = x
df['groupby'] = pd.cut(x,bins, right = False,include_lowest=True)
df_cnt = df['groupby'].value_counts().reset_index()
df_cnt.loc[:,'mini'] = df_cnt['index'].astype(str).map(lambda x:re.findall('\[(.*)\,',x)[0]).astype(int)
df_cnt.loc[:,'maxi'] = df_cnt['index'].astype(str).map(lambda x:re.findall('\,(.*)\)',x)[0]).astype(int)
df_cnt.loc[:,'width'] = df_cnt['maxi']- df_cnt['mini']
df_cnt.sort_values('mini',ascending = True,inplace = True)
df_cnt.reset_index(inplace = True,drop = True)
fig = plt.figure()
ax1 = fig.add_subplot(111)
for i in df_cnt.index:
rect = plt.Rectangle((df_cnt.loc[i,'mini'],0),df_cnt.loc[i,'width'],df_cnt.loc[i,'groupby'])
# Rectangle(xy=(0, 0), width=10, height=18, angle=0)
# Rectangle(xy=(10, 0), width=10, height=11, angle=0)
# Rectangle(xy=(20, 0), width=10, height=15, angle=0)
# Rectangle(xy=(30, 0), width=10, height=10, angle=0)
# Rectangle(xy=(40, 0), width=10, height=6, angle=0)
# Rectangle(xy=(50, 0), width=10, height=4, angle=0)
# Rectangle(xy=(60, 0), width=10, height=11, angle=0)
# Rectangle(xy=(70, 0), width=10, height=9, angle=0)
# Rectangle(xy=(80, 0), width=10, height=8, angle=0)
# Rectangle(xy=(90, 0), width=10, height=8, angle=0)
ax1.add_patch(rect)
ax1.set_xlim(0, 100)
ax1.set_ylim(0, 20)
2) bar-柱状图
matplotlib.pyplot.bar(left, height, alpha=1, width=0.8, color=, edgecolor=, label=, lw=3)
下面是一些常用的参数:
- left:x轴的位置序列,一般采用range函数产生一个序列,但是有时候可以是字符串
- height:y轴的数值序列,也就是柱形图的高度,一般就是我们需要展示的数据;
- alpha:透明度,值越小越透明
- width:为柱形图的宽度,一般这是为0.8即可;
- color或facecolor:柱形图填充的颜色;
- edgecolor:图形边缘颜色
- label:解释每个图像代表的含义,这个参数是为legend()函数做铺垫的,表示该次bar的标签
import matplotlib as mpl x = np.arange(1,17) y = x+1 plt.bar(x, y, alpha=0.5, width=0.5, color='Aqua', edgecolor='SpringGreen', label='The First Bar', lw=3)
Rectangle
矩形类绘制柱状图
fig = plt.figure()
ax1 = fig.add_subplot(111)
for i in range(1,17):
rect = plt.Rectangle((i+0.25,0),0.5,i)
#class matplotlib.patches.Rectangle(xy, width, height, angle=0.0, **kwargs)。
#在这里(i+0.25,0)是xy的元组,0是距离X轴的距离
ax1.add_patch(rect)
ax1.set_xlim(0, 16)
ax1.set_ylim(0, 16)
plt.show()
b. Polygon-多边形
matplotlib.patches.Polygon类是多边形类。其基类是matplotlib.patches.Patch,它的构造函数:
class matplotlib.patches.Polygon(xy, closed=True, **kwargs)
xy是一个N×2的numpy array,为多边形的顶点。
closed为True则指定多边形将起点和终点重合从而显式关闭多边形。
matplotlib.patches.Polygon类中常用的是fill类,它是基于xy绘制一个填充的多边形,它的定义:
matplotlib.pyplot.fill(_args, data=None, *_kwargs)
参数说明 : 关于x、y和color的序列,其中color是可选的参数,每个多边形都是由其节点的x和y位置列表定义的,后面可以选择一个颜色说明符。您可以通过提供多个x、y、[颜色]组来绘制多个多边形。
fill绘制图形。
import matplotlib.pyplot as plt
x = np.linspace(0, 5 * np.pi, 1000)
y1 = np.sin(1*x)
y2 = np.sin(x)
plt.fill(x, y1, color = "b", alpha = 0.3)
c. Wedge-契形
matplotlib.patches.Polygon类是多边形类。其基类是matplotlib.patches.Patch,它的构造函数:
class matplotlib.patches.Wedge(center, r, theta1, theta2, width=None, **kwargs)
一个Wedge-契形 是以坐标x,y为中心,半径为r,从θ1扫到θ2(单位是度)。
如果宽度给定,则从内半径r -宽度到外半径r画出部分楔形。wedge中比较常见的是绘制饼状图。
matplotlib.pyplot.pie语法:
matplotlib.pyplot.pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1, startangle=0, radius=1, counterclock=True, wedgeprops=None, textprops=None, center=0, 0, frame=False, rotatelabels=False, *, normalize=None, data=None)
制作数据x的饼图,每个楔子的面积用x/sum(x)表示。
其中最主要的参数是前4个:
- x:契型的形状,一维数组。
- explode:如果不是等于None,则是一个len(x)数组,它指定用于偏移每个楔形块的半径的分数。
- labels:用于指定每个契型块的标记,取值是列表或为None。
- colors:饼图循环使用的颜色序列。如果取值为None,将使用当前活动循环中的颜色。
- startangle:饼状图开始的绘制的角度。
pie绘制饼状图
import matplotlib.pyplot as plt
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0, 0, 0.4)
fig1, ax1 = plt.subplots()
ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90)
ax1.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
plt.show()
wedge
绘制饼图(OS:这方法真的有人用?)
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Wedge
from matplotlib.collections import PatchCollection
fig = plt.figure()
ax1 = fig.add_subplot(111)
theta1 = 0
sizes = [15, 30, 45, 10]
patches = []
patches += [
Wedge((0.3, 0.3), .2, 0, 54), # Full circle
Wedge((0.3, 0.3), .2, 54, 162), # Full ring
Wedge((0.3, 0.3), .2, 162, 324), # Full sector
Wedge((0.3, 0.3), .2, 324, 360), # Ring sector
]
colors = 100 * np.random.rand(len(patches))
p = PatchCollection(patches, alpha=0.4)
p.set_array(colors)
ax1.add_collection(p)
plt.show()
3. collections
collections类是用来绘制一组对象的集合,collections有许多不同的子类,如RegularPolyCollection, CircleCollection, Pathcollection, 分别对应不同的集合子类型。其中比较常用的就是散点图,它是属于PathCollection子类,scatter方法提供了该类的封装,根据x与y绘制不同大小或颜色标记的散点图。 它的构造方法:
Axes.scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=, edgecolors=None, _, plotnonfinite=False, data=None, *_kwargs)
其中最主要的参数是前5个:
- x:数据点x轴的位置
- y:数据点y轴的位置
- s:尺寸大小
- c:可以是单个颜色格式的字符串,也可以是一系列颜色
- marker: 标记的类型
scatter绘制散点图,气泡图
x = np.arange(0,100,1)
y = np.random.randint(100,size= 100)
s = [np.sqrt(i*n) for i,n in zip(x,y)] #绘制大小
plt.scatter(x,y,s=s)
plt.show()
4. images
images是matplotlib中绘制image图像的类,其中最常用的imshow可以根据数组绘制成图像,它的构造函数:
imshow(X, cmap=None, norm=None, aspect=None,
interpolation=None, alpha=None, vmin=None, vmax=None,
origin=None, extent=None, shape=None, filternorm=1,
filterrad=4.0, imlim=None, resample=None, url=None, **kwargs)
X
可以使类似数组的对象,或者是PIL类型图像,其中,数组对象可选shape为:(M, N)
单纯的二维数组,元素是标量数据,会通过colormap
展示(M, N, 3)
RGB三通道图像,元素值可以是0−10−1之间的float
或者0−2550−255之间的int
(M, N, 4)
RGBA图像,多出来的一维属性,比如是透明度,其元素值和3通道的一样,可以是0−10−1之间的float
或者0−2550−255之间的int
- ※
M
代表rows
,N
代表colums
- ※ 超过元素限定范围的元素值将被clipped
- ※
cmap
str
或matplotlib.colors.Colormap
类型,用于将标量数据映射到颜色的Colormap
实例或已注册的Colormap
名称。- ※ 只对二维数组有效,RGB(A)将自动忽略
norm
在使用cmap
之前,用来将二维数组数据归一化到[0,1][0,1],默认是线性的,最小值对应00,最大值对应11。- 这要注意,不然每次画图最大最小值不一样,色彩不好比较。
interpolation
插值方法,默认'nearest'
,可以支持的方法有:案例都有
alpha
透明度,00表示透明,11表示不透明vmin
,vmax
当输入的时二维数组标量数据并且没有明确的norm
时,vmin
和vmax
定义colormap
覆盖的数据范围,默认情况下,colormap
覆盖所提供的值的完整范围数据当
norm
给定时,这两个参数无效origin
坐标轴的样式,可选值为upper
和lower
,其对应坐标系样式如下图※
M
代表rows
,N
代表colums
使用imshow画图时首先需要传入一个数组,数组对应的是空间内的像素位置和像素点的值,interpolation参数可以设置不同的差值方法,具体效果如下。
import matplotlib.pyplot as plt
import numpy as np
methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16',
'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']
grid = np.random.rand(4, 4) #生成随机数组
fig, axs = plt.subplots(nrows=3, ncols=6, figsize=(9, 6),
subplot_kw={'xticks': [], 'yticks': []}) #隐藏刻度
for ax, interp_method in zip(axs.flat, methods):
ax.imshow(grid, interpolation=interp_method, cmap='viridis')
ax.set_title(str(interp_method))
plt.tight_layout()
plt.show()
第二个相关图例子:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
vegetables = ["cucumber", "tomato", "lettuce", "asparagus",
"potato", "wheat", "barley"]
farmers = ["Farmer Joe", "Upland Bros.", "Smith Gardening",
"Agrifun", "Organiculture", "BioGoods Ltd.", "Cornylee Corp."]
harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],
[2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],
[1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],
[0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],
[0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],
[1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],
[0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3]])
fig, ax = plt.subplots(figsize=(9, 9)) #创建画图
im = ax.imshow(harvest) #导入数据集
ax.set_xticks(np.arange(len(farmers))) #设置轴标签
ax.set_yticks(np.arange(len(vegetables)))
ax.set_xticklabels(farmers) #将轴标签替换成对应标签
ax.set_yticklabels(vegetables)
#plt.setp(ax.get_xticklabels(), rotation=45, ha="right",
#rotation_mode="anchor") #旋转X轴labels
for i in range(len(vegetables)):
for j in range(len(farmers)):
text = ax.text(j, i, harvest[i, j],
ha="center", va="center", color="w") #显示数字
ax.set_title("Harvest of local farmers (in tons/year)") #设置标题
fig.tight_layout() #自动适应画布
四、对象容器 - Object container
我在第二章第1节Artist中有讲解。这里把教材抄下来,方便后期归类查询。
容器会包含一些primitives
,并且容器还有它自身的属性。
比如Axes Artist
,它是一种容器,它包含了很多primitives
,比如Line2D
,Text
;同时,它也有自身的属性,比如xscal
,用来控制X轴是linear
还是log
的。
1. Figure容器
matplotlib.figure.Figure
是Artist
最顶层的container
-对象容器,它包含了图表中的所有元素。一张图表的背景就是在Figure.patch
的一个矩形Rectangle
。
当我们向图表添加Figure.add_subplot()
或者Figure.add_axes()
元素时,这些都会被添加到Figure.axes
列表中。
In [19]:
fig = plt.figure()
ax1 = fig.add_subplot(211) # 作一幅2*1的图,选择第1个子图
ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3]) # 位置参数,四个数分别代表了(left,bottom,width,height)
print(ax1)
print(fig.axes) # fig.axes 中包含了subplot和axes两个实例, 刚刚添加的
由于Figure
维持了current axes
,因此你不应该手动的从Figure.axes
列表中添加删除元素,而是要通过Figure.add_subplot()
、Figure.add_axes()
来添加元素,通过Figure.delaxes()
来删除元素。但是你可以迭代或者访问Figure.axes
中的Axes
,然后修改这个Axes
的属性。
比如下面的遍历axes里的内容,并且添加网格线:
fig = plt.figure()
ax1 = fig.add_subplot(211)
for ax in fig.axes:
ax.grid(True)
<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/2610909/1608195760008-41173cd5-5117-47b4-b920-7f2774da2a5f.png#align=left&display=inline&height=134&margin=%5Bobject%20Object%5D&name=image.png&originHeight=134&originWidth=386&size=3280&status=done&style=none&width=386)<br />`Figure`也有它自己的`text、line、patch、image`。你可以直接通过`add primitive`语句直接添加。但是注意`Figure`默认的坐标系是以像素为单位,你可能需要转换成figure坐标系:(0,0)表示左下点,(1,1)表示右上点。
Figure容器的常见属性:Figure.patch
属性:Figure的背景矩形Figure.axes
属性:一个Axes实例的列表(包括Subplot)Figure.images
属性:一个FigureImages patch列表Figure.lines
属性:一个Line2D实例的列表(很少使用)Figure.legends
属性:一个Figure Legend实例列表(不同于Axes.legends)Figure.texts
属性:一个Figure Text实例列表
2. Axes容器
matplotlib.axes.Axes
是matplotlib的核心。大量的用于绘图的Artist
存放在它内部,并且它有许多辅助方法来创建和添加Artist
给它自己,而且它也有许多赋值方法来访问和修改这些Artist
。
和Figure
容器类似,Axes
包含了一个patch属性,对于笛卡尔坐标系而言,它是一个Rectangle
;对于极坐标而言,它是一个Circle
。这个patch属性决定了绘图区域的形状、背景和边框。
In [21]:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
fig = plt.figure()
ax = fig.add_subplot(111)
rect = ax.patch # axes的patch是一个Rectangle实例
rect.set_facecolor('green')
Axes
有许多方法用于绘图,如.plot()、.text()、.hist()、.imshow()
等方法用于创建大多数常见的primitive
(如Line2D,Rectangle,Text,Image
等等)。在primitives
中已经涉及,不再赘述。
Subplot就是一个特殊的Axes,其实例是位于网格中某个区域的Subplot实例。其实你也可以在任意区域创建Axes,通过Figure.add_axes([left,bottom,width,height])来创建一个任意区域的Axes,其中left,bottom,width,height都是[0—1]之间的浮点数,他们代表了相对于Figure的坐标。
你不应该直接通过Axes.lines
和Axes.patches
列表来添加图表。因为当创建或添加一个对象到图表中时,Axes
会做许多自动化的工作:
它会设置Artist中figure和axes的属性,同时默认Axes的转换;
它也会检视Artist中的数据,来更新数据结构,这样数据范围和呈现方式可以根据作图范围自动调整。
你也可以使用Axes的辅助方法.add_line()
和.add_patch()
方法来直接添加。
另外Axes还包含两个最重要的Artist container:ax.xaxis
:XAxis对象的实例,用于处理x轴tick以及label的绘制ax.yaxis
:YAxis对象的实例,用于处理y轴tick以及label的绘制
会在下面章节详细说明。
Axes容器的常见属性有:artists
: Artist实例列表 patch
: Axes所在的矩形实例 collections
: Collection实例 images
: Axes图像 legends
: Legend 实例 lines
: Line2D 实例 patches
: Patch 实例 texts
: Text 实例 xaxis
: matplotlib.axis.XAxis 实例 yaxis
: matplotlib.axis.YAxis 实例
3. Axis容器
matplotlib.axis.Axis
实例处理tick line
、grid line
、tick label
以及axis label
的绘制,它包括坐标轴上的刻度线、刻度label
、坐标网格、坐标轴标题。通常你可以独立的配置y轴的左边刻度以及右边的刻度,也可以独立地配置x轴的上边刻度以及下边的刻度。
刻度包括主刻度和次刻度,它们都是Tick刻度对象。Axis
也存储了用于自适应,平移以及缩放的data_interval
和view_interval
。它还有Locator实例和Formatter实例用于控制刻度线的位置以及刻度label。
每个Axis都有一个label
属性,也有主刻度列表和次刻度列表。这些ticks
是axis.XTick
和axis.YTick
实例,它们包含着line primitive
以及text primitive
用来渲染刻度线以及刻度文本。
刻度是动态创建的,只有在需要创建的时候才创建(比如缩放的时候)。Axis也提供了一些辅助方法来获取刻度文本、刻度线位置等等:
常见的如下:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
fig, ax = plt.subplots()
x = range(0,5)
y = [2,5,7,8,10]
plt.plot(x, y, '-')
axis = ax.xaxis # axis为X轴对象
axis.get_ticklocs() # 获取刻度线位置
axis.get_ticklabels() # 获取刻度label列表(一个Text实例的列表)。 可以通过minor=True|False关键字参数控制输出minor还是major的tick label。
axis.get_ticklines() # 获取刻度线列表(一个Line2D实例的列表)。 可以通过minor=True|False关键字参数控制输出minor还是major的tick line。
axis.get_data_interval()# 获取轴刻度间隔
axis.get_view_interval()# 获取轴视角(位置)的间隔
下面的例子展示了如何调整一些轴和刻度的属性(忽略美观度,仅作调整参考):
fig = plt.figure(figsize=(9,9)) # 创建一个新图表
rect = fig.patch # 矩形实例并将其设为黄色
rect.set_facecolor('lightgoldenrodyellow')
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4]) # 创一个axes对象,从(0.1,0.3)的位置开始,宽和高都为0.4,
rect = ax1.patch # ax1的矩形设为灰色
rect.set_facecolor('lightslategray')
for label in ax1.xaxis.get_ticklabels():
# 调用x轴刻度标签实例,是一个text实例
label.set_color('red') # 颜色
label.set_rotation(45) # 旋转角度
label.set_fontsize(16) # 字体大小
for line in ax1.yaxis.get_ticklines():
# 调用y轴刻度线条实例, 是一个Line2D实例
line.set_color('green') # 颜色
line.set_markersize(25) # marker大小
line.set_markeredgewidth(2)# marker粗细
plt.show()
4. Tick容器
matplotlib.axis.Tick
是从Figure
到Axes
到Axis
到Tick
中最末端的容器对象。Tick
包含了tick
、grid line
实例以及对应的label
。
所有的这些都可以通过Tick
的属性获取,常见的tick
属性有Tick.tick1line
:Line2D实例Tick.tick2line
:Line2D实例Tick.gridline
:Line2D实例Tick.label1
:Text实例Tick.label2
:Text实例
y轴分为左右两个,因此tick1对应左侧的轴;tick2对应右侧的轴。
x轴分为上下两个,因此tick1对应下侧的轴;tick2对应上侧的轴。
下面的例子展示了,如何将Y轴右边轴设为主轴,并将标签设置为美元符号且为绿色:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
fig, ax = plt.subplots()
ax.plot(100*np.random.rand(20))
# 设置ticker的显示格式
formatter = matplotlib.ticker.FormatStrFormatter('$%1.2f')
ax.yaxis.set_major_formatter(formatter)
# 设置ticker的参数,右侧为主轴,颜色为绿色
ax.yaxis.set_tick_params(which='major', labelcolor='green',
labelleft=False, labelright=True)
plt.show()
课后习题:
思考题
primitives 和 container的区别和联系是什么?
1.
primitive
是基本要素,它包含一些我们要在绘图区作图用到的标准图形对象,如曲线Line2D,文字text,矩形Rectangle,图像image等。 2.container
是容器,即用来装基本要素的地方,包括图形figure、坐标系Axes和坐标轴Axis。 **>四个容器的联系和区别是么?他们分别控制一张图表的哪些要素?
a.Figure控制画布,底层 b.Axes控制图片,类型、方式什么的,中层 c.Axis控制,坐标轴,上层 d.Tick控制坐标轴刻度,顶层
绘图题
- 教程中展示的案例都是单一图,请自行创建数据,画出包含6个子图的线图,要求:
子图排布是 2 * 3 (2行 3列);
线图可用教程中line2D方法绘制;
需要设置每个子图的横坐标和纵坐标刻度; 并设置整个图的标题,横坐标名称,以及纵坐标名称 ```python-- coding: utf-8 --
“”” Created on Thu Dec 17 15:29:21 2020
@author: Administrator “””
import matplotlib.pyplot as plt import numpy as np import random plt.rcParams[‘font.sans-serif’] = [‘SimHei’] # 用来正常显示中文标签 plt.rcParams[‘axes.unicode_minus’] = False # 用来正常显示负号
def randomcolor(): colorArr = [‘1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’,’A’,’B’,’C’,’D’,’E’,’F’] color = “” for i in range(6): color += colorArr[random.randint(0,14)] return “#”+color
fig = plt.figure()
for i in range(1,7): x = np.arange(0,100,20) y = np.random.randint(0,20,5) ax= fig.add_subplot(2,3,i) ax.plot(x,y,color=randomcolor()) plt.xlabel(“横坐标”) plt.ylabel(“纵坐标”) fig.suptitle(‘这是figure标题’)
> ![image.png](https://cdn.nlark.com/yuque/0/2020/png/2610909/1608202844848-533191fd-cd4b-4179-a2ee-1b5885265f1f.png#align=left&display=inline&height=288&margin=%5Bobject%20Object%5D&name=image.png&originHeight=288&originWidth=379&size=24328&status=done&style=none&width=379)
2. 分别用一组长方形柱和填充面积的方式模仿画出下图,函数 y = -1 * (x - 2) * (x - 8) +10 ![](https://cdn.nlark.com/yuque/__latex/374070175ebbf4b9382b71d5cae80233.svg#card=math&code=y%3D-1%5Ctimes%28x-2%29%5Ctimes%28x-8%29%2B10&height=20&width=234)在区间[2,9]![](https://cdn.nlark.com/yuque/__latex/87c5faaa29e7cd52c35bd776829fa6f7.svg#card=math&code=%5B2%2C9%5D&height=20&width=33)的积分面积![](https://cdn.nlark.com/yuque/0/2020/png/2610909/1608195626261-84200f13-ff9b-40fe-9ef2-7981a9a7b1c4.png#align=left&display=inline&height=252&margin=%5Bobject%20Object%5D&originHeight=252&originWidth=378&size=0&status=done&style=none&width=378)![](https://cdn.nlark.com/yuque/0/2020/png/2610909/1608195626156-3d2ada9e-6f6c-49bc-a57f-761a05931f0a.png#align=left&display=inline&height=252&margin=%5Bobject%20Object%5D&originHeight=252&originWidth=378&size=0&status=done&style=none&width=378)
```python
import numpy as np
from matplotlib import pyplot as plt
# from matplotlib.patches import Polygon
def func(x):
return -1 * (x - 2) * (x - 8) +10
x = np.linspace(2,9,5000)
y = func(x)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y,color='r',lw=2)
width = (9-2)/5000
for i,v in zip(x,y):
rect = plt.Rectangle((i,0),width,v)
ax.add_patch(rect)
ax.set_xlim(0, 10)
ax.set_ylim(0, 20)