matplotlib基本使用方法

【微语】人生有可为之事,也有不可为之事。可为之事,当尽力为之,此谓尽性,不可为之事,当尽心为之,此谓知命。

三人行必有我师

官方参考API:https://matplotlib.org/tutorials/index.html

Bilibili教程:https://www.bilibili.com/video/av16378354/?

博客园参考:https://www.cnblogs.com/xubing-613/p/5895948.html

快速入门matplotlib:

# 导入库
import matplotlib.pyplot as plt
import numpy as np

首先通过 np.linspace() 方式生成 x,它包含了 50 个元素的数组,这 50 个元素均匀的分布在 [0, 2pi] 的区间上

x = np.linspace(0, 2 * np.pi, 50)
y = np.sin(x)

有了 x 和 y 数据之后,我们通过 plt.plot(x, y) 来画出图形,并通过 plt.show() 来显示。

还可以plt.figure(num=2,figsize = (8,5),facecolor='yellow',edgecolor='blue') 来指定图片名称 、图片宽高、图片前景色、边框颜色

plt.figure(num=2,figsize = (8,5),facecolor='yellow',edgecolor='blue') 
plt.plot(x, y) plt.show()

在一个图里绘制多条曲线

有时候,可能需要在一个图纸里绘制多个图形,这里我们同时绘制了 (x, y1), (x, y2)两个图形

x = np.linspace(-3,3,50)
y1 = 2*x +1
y2 = x*x

plt.plot(x, y1)
plt.plot(x, y2)
plt.show()

绘制出图形之后,可以自己调整更多的样式,比如颜色、点、线

plt.plot(x,y1,'y*-')    #y 表示黄色,* 表示 星标的点,- 表示实线
plt.plot(x,y2,'m--')    #m表示品红色, --表示虚线

设置标题

plt.title('y1&y2')

设置坐标轴(范围和名称)

plt.xlim((0, np.pi + 1))
plt.ylim((-3, 3))
plt.xlabel('X')
plt.ylabel('Y')

##通过 xlim 和 ylim 来设限定轴的范围,通过 xlabel 和 ylabel 来设置轴的名称。
##此外,我们也可以通过 xticks 和 yticks 来设置轴的刻度
plt.xticks((0, np.pi * 0.5, np.pi, np.pi * 1.5, np.pi * 2))

x = np.linspace(0,2*np.pi,100)
y1 = np.sin(2*x)
plt.plot(x,y1)
xxticks = np.linspace(0,7,8)
plt.xticks(xxticks)
#将-1 对应为really bad,可以使用r'$badalpha -0.5$' 将字体转为数学图表常用字体 alpha = α
plt.yticks([-1,-0.5,0,0.5,1],
           [r'$really bad-1$',r'$badalpha -0.5$',r'$normal0$',r'$good0.5$',r'$really good1$'])

plt.show()

移动坐标轴 plt.gca()获取4个轴

 

 1 import numpy as np
 2 import matplotlib.pyplot as plt
 3 
 4 x = np.linspace(-3, 3, 50)
 5 y1 = 2 * x + 1
 6 y2 = x ** 2
 7 plt.figure()
 8 plt.plot(x, y1)
 9 plt.plot(x, y2, color='red', linewidth=2, linestyle='--')
10 # plt.xlim(-1,2)
11 # plt.ylim(-2,3)
12 
13 # gca 'get current axes' 获取图像的4个轴right、top、bottom、left
14 ax = plt.gca()
15 # 设置有top和right轴颜色为空
16 ax.spines['right'].set_color('none')
17 ax.spines['top'].set_color('none')
18 # 设置底边轴的移动范围,移动到y轴的0位置
19 # data:移动y轴的位置  outward:  axes:0.0 - 1.0之间的值,整个轴上的比例  center:('axes',0.5) zero:('data',0.0)
20 ax.spines['bottom'].set_position(('data', 0))
21 ax.spines['left'].set_position(('data', 0))
22 # 利用axes对象设置轴线的显示范围,与plt.xlim(-1,2)和plt.ylim(-2,3)的作用相同
23 ax.set_xlim(-1, 2)
24 ax.set_ylim(-2, 3)
25 # 利用axes对象设置坐标轴的标签,与xlabel('x data')效果相同
26 ax.set_xlabel('x data')
27 ax.set_ylabel('y data')
28 
29 # 设置坐标轴上的数字显示的位置,top:显示在顶部  bottom:显示在底部,默认是none
30 ax.xaxis.set_ticks_position('bottom')
31 ax.yaxis.set_ticks_position('left')
32 plt.show()

 设置x轴y轴标签边框

"""设置xy轴便签底部边框"""
for label in ax.get_xticklabels()+ax.get_yticklabels():
    label.set_fontsize(12)    
    label.set_bbox(dict(facecolor='yellow',edgecolor='blue',alpha=0.5))

设置legend图例

设置 label 和 legend 的目的就是为了区分出每个数据对应的图形名称

l1 = plt.plot(x, y1, label="2*x+1")
l2 = plt.plot(x, y2, label="x*x")
# plt.legend(handles=[l1,l2],labels=['y1线','y2线'],loc='best') #loc有upper upper right bottom...
plt.legend(loc='best')
plt.show()

添加网格grid()

#linestyle(ls)   linewidth(lw)
plt.plot(x,y,ls='b-',lw=2,label='sin(x)')
plt.legend()

#linestyle 设置网格线类型 color设置颜色
plt.grid(lintstyle=':',color='r')

 设置水平垂直参考线axhline() / axvline()

设置平行于x轴/y轴的参考区域axhspan() / axvspan()

在图中添加注解 即指向性注释文本annotate()

有时候我们需要对特定的点进行标注,我们可以使用 plt.annotate()函数来实现。

这里我们要标注的点是 (x0, y0) = (π, 0)我们也可以使用 plt.text() 函数来添加注释。

x = np.linspace(0,2*np.pi,100)
y = np.sin(x)
plt.plot(x, y)

x0 = np.pi
y0 = 0

# 画出标注点
plt.scatter(x0, y0, s=50)

plt.annotate('sin(np.pi)=%s' % y0, xy=(np.pi, 0), xycoords='data', xytext=(+30, -30),
             textcoords='offset points', fontsize=16,
             arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))

plt.text(0.5, -0.25, "sin(np.pi) = 0", fontdict={'size': 16, 'color': 'r'})

plt.show()

对于 annotate 函数的参数解释:

  • 'sin(np.pi)=%s' % y0 代表标注的内容,可以通过字符串 %s 将 y0 的值传入字符串;

  • 参数 xycoords='data' 是说基于数据的值来选位置;

  • xytext=(+30, -30) 和 textcoords='offset points' 表示对于标注位置的描述 和 xy 偏差值,即标注位置是 xy 位置向右移动 30,向下移动30;

  • arrowprops 是对图中箭头类型和箭头弧度的设置,需要用 dict 形式传入。

使用子图subplot()

有时候我们需要将多张子图展示在一起,可以使用 subplot() 实现。即在调用 plot() 函数之前需要先调用 subplot() 函数。

该函数的第一个参数代表子图的总行数,第二个参数代表子图的总列数,第三个参数代表活跃区域

可以表示为subplot(2,3,1) 2行3列第一个图,也可表示为subplot(231)

ax1 = plt.subplot(2, 2, 1) # (行,列,活跃区)
plt.plot(x, np.sin(x), 'r')

ax2 = plt.subplot(2, 2, 2, sharey=ax1) # 与 ax1 共享y轴
plt.plot(x, 2 * np.sin(x), 'g')

ax3 = plt.subplot(2, 2, 3)
plt.plot(x, np.cos(x), 'b')

ax4 = plt.subplot(2, 2, 4, sharey=ax3) # 与 ax3 共享y轴
plt.plot(x, 2 * np.cos(x), 'y')

plt.show()

上面的 subplot(2, 2, x) 表示将图像窗口分为 2 行 2 列。x 表示当前子图所在的活跃区。

可以看到,上面的每个子图的大小都是一样的。有时候我们需要不同大小的子图。比如将上面第一张子图完全放置在第一行,其他的子图都放在第二行。

ax1 = plt.subplot(2, 1, 1) # (行,列,活跃区)
plt.plot(x, np.sin(x), 'r')

ax2 = plt.subplot(2, 3, 4)
plt.plot(x, 2 * np.sin(x), 'g')

ax3 = plt.subplot(2, 3, 5, sharey=ax2)
plt.plot(x, np.cos(x), 'b')

ax4 = plt.subplot(2, 3, 6, sharey=ax2)
plt.plot(x, 2 * np.cos(x), 'y')

plt.show()

简单解释下,plt.subplot(2, 1, 1) 将图像窗口分为了 2 行 1 列, 当前活跃区为 1。

使用 plt.subplot(2, 3, 4) 将整个图像窗口分为 2 行 3 列, 当前活跃区为 4。

解释下为什么活跃区为 4,因为上一步中使用 plt.subplot(2, 1, 1) 将整个图像窗口分为 2 行 1 列, 第1个小图占用了第1个位置, 也就是整个第1行. 这一步中使用 plt.subplot(2, 3, 4) 将整个图像窗口分为 2 行 3 列, 于是整个图像窗口的第1行就变成了3列, 也就是成了3个位置, 于是第2行的第1个位置是整个图像窗口的第4个位置。

 1 import numpy as np
 2 import matplotlib.pyplot as plt
 3 
 4 """第一种plt.subplot2grid()"""
 5 x = np.linspace(0,6,30)
 6 
 7 ax1 = plt.subplot2grid((3,3),(0,0),rowspan=1,colspan=3)
 8 ax1.plot(x,2*x+1)
 9 ax1.set_title('first image')
10 
11 ax2 = plt.subplot2grid((3,3),(1,0),rowspan=1,colspan=2)
12 ax2.plot(x,x*x)
13 ax2.set_title('second image')
14 
15 ax3 = plt.subplot2grid((3,3),(1,2),rowspan=2,colspan=1)
16 ax3.plot(x,np.sin(x))
17 ax3.set_title('third image')
18 
19 ax4 = plt.subplot2grid((3,3),(2,0),rowspan=1,colspan=1)
20 ax4.plot(x,np.cos(x))
21 ax4.set_title('forth image')
22 
23 ax5 = plt.subplot2grid((3,3),(2,1),rowspan=1,colspan=1)
24 ax5.plot(x,np.exp(x))
25 ax5.set_title('fifth image')
26 
27 plt.show()

 主次坐标轴

"""主次坐标轴"""
x = np.arange(0,10,0.1)
y1 = np.exp(x)
y2 = -y1
ax1 = plt.subplot()
ax2 = ax1.twinx()
ax1.plot(x,y1,'g-',)
ax2.plot(x,y2,'r--')

ax1.set_xlabel('x data')
ax1.set_ylabel('y1 data',color='g')
ax2.set_ylabel('y2 data',color='b')

plt.show()

其他一些常见的图形

散点图

x = np.linspace(-3,3,30)
y = 2*x + 1
plt.scatter(x,y,s=30,c='red')    #s指定点大小,c指定点颜色

x = np.random.normal(0,1,1024)
y = np.random.normal(0,1,1024)
colors = np.arctan2(x,y)    #设置颜色

plt.figure()
# plt.plot(x,y,linewidth=2,linestyle='--')
plt.scatter(x,y,s=30,c=colors,alpha=0.5)    #s指定点大小,c指定点颜色
plt.xlim((-2,2))
plt.ylim((-2,2))
#隐藏x ytick
plt.xticks(())
plt.yticks(())

柱状图(直方图)

n, bins, patches = plt.hist(arr, bins=10, normed=0, facecolor='black', edgecolor='black',alpha=1,histtype='bar')

hist的参数非常多,但常用的就这六个,只有第一个是必须的,后面四个可选

arr: 需要计算直方图的一维数组

bins: 直方图的柱数,可选项,默认为10

normed: 是否将得到的直方图向量归一化。默认为0

facecolor: 直方图颜色

edgecolor: 直方图边框颜色

alpha: 透明度

histtype: 直方图类型,‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’

返回值 :

n: 直方图向量,是否归一化由参数normed设定

bins: 返回各个bin的区间范围

patches: 返回每个bin里面包含的数据,是一个list

#补充知识点:
#NumPy把多维数组变一维数组/多个一维数组连接为一维数组的方法
#1.flatten函数能将多维数组变成一位数组 
arr1=np.array([[65,76,89,91],[31,42,45,61]],float)
arr2 = arr1.flatten()
print(arr2)
array([ 65.,  76.,  89.,  91.,  31.,  42.,  45.,  61.])
#2.concatenate函数是用于数组的连接操作,可将多个一维数组连接为一维数组 import numpy as np arr1=np.array([10,22],float) arr2=np.array([31,42,45,61],float) arr3=np.array([65,76,89,91],float) arr4 = np.concatenate((arr1,arr2,arr3)) print(arr4) array([ 10., 22., 31., 42., 45., 61., 65., 76., 89., 91.])
k = 10
x = np.arange(k)
y = np.random.rand(k)
plt.bar(x, y)     # 画出 x 和 y 的柱状图

# 增加数值
for x, y in zip(x, y):
    plt.text(x, y , '%.2f' % y, ha='center', va='bottom')

plt.show()

生成数据 x 和 y 之后,调用 plt.bar 函数绘制出柱状图,然后通过 plt.text 标注数值,设置参数 ha='center' 横向居中对齐,设置 va='bottom'纵向底部(顶部)对齐

中文乱码解决

Matplotlib 有个让人恼火的问题是,默认情况下,Matplotlib 中文会乱码

x = ['北京', '上海', '深圳', '广州']
y = [60000, 58000, 50000, 52000]
plt.plot(x, y)
plt.show()

只需要配置下后台字体即可

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

plt.plot(x, y)
plt.show()

原文地址:https://www.cnblogs.com/XJT2018/p/9988132.html