官方参考API:https://matplotlib.org/tutorials/index.html
官方demo :https://matplotlib.org/gallery/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()