Python 可视化模块 Matplotlib 的使用 | 字数总计: 2.5k | 阅读时长: 11分钟 | 阅读量:
Matplotlib 是 Python 中的数据可视化软件包,支持跨平台。Jonh D. Hunter 于 2002 年开始编写,2003 年发布第一版,并加入 BSD 开源软件组织。Matplotlib 提供了面向绘图对象的 API,能够实现常用图像的绘制,并能配合 Python GUI 工具(如 PyQt, Tkinter 等)把图像嵌入到应用程序中,同时也支持以脚本形式嵌入 IPython Shell, Jupyter notebook, Web 应用服务器中使用.
Matplotlib 架构和图像构成 Matplotlib 架构由 3 个层次构成,分别是:
后端层。作为最底层,它包含 3 个基类,分别是 FigureCanvas(图层画布,提供绘图的画布)、Renderer(绘图操作,提供画布上绘图的方法)、Event(事件处理,处理鼠标、键盘事件);
美工层。提供绘图的标题、坐标刻度、轴标签;
脚本层。负责生成图像和坐标系。
Matplotlib 图像由 4 个层次构成,分别是:
Figure:画布,包含所有元素,如标题、轴线等;
Axes:绘图区,或轴域区;
Axis:坐标轴,包含轴长、轴标签和刻度等;
Artist:文本对象(title, label)等能看到的所有对象。
Matplotlib 安装与使用 安装 1 2 3 4 5 6 pip install matplotlib pip install matplotlib==3.2.2 pip uninstall matplotlib
面向对象绘图 Python 是一门面向对象的语言,Matplotlib 也提供了对象类,如画布类、绘图区类等,下面根据类实例化方法画一个图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import matplotlib.pyplot as plt import numpy as np x = np.linspace(-5 , 5 , 101 ) y = np.cos(x) fig = plt.figure(figsize=(3 , 3 ), dpi=100 ) ax = fig.add_axes( rect=[0 , 0 , 1 , 1 ] ) ax.set_title("余弦曲线" ) ax.set_xlabel("弧度" ) ax.set_ylabel("余弦值" ) ax.plot( x, y, color="cyan" , marker="o" , linestyle="dashed" , linewidth=1 , markersize=6 ) plt.show()
简单绘图 上面的面向对象绘图根据常规绘图的步骤进行,先创建画布,然后创建绘图区,最后绘图。有时,为了快速绘图,我们可以直接一条命令绘图,它会自动创建画布和绘图区。
1 2 3 4 5 6 7 8 9 10 11 12 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) y = np.cos(x) plt.plot( x, y, color="purple" , marker="^" , linestyle="dashed" , linewidth=1 , markersize=6 ) plt.title("余弦曲线" ) plt.xlabel("弧度" ) plt.ylabel("余弦值" ) plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) plt.plot( x, np.cos(x), color="purple" , marker="^" , linestyle="dashed" , linewidth=1 , markersize=6 , label="余弦" , ) plt.plot(x, np.sin(x), "go" , label="正弦" ) plt.title("正余弦曲线" ) plt.xlabel("弧度" ) plt.ylabel("正余弦值" ) plt.legend() plt.show()
Matplotlib subplot 绘多幅图-遮挡 有时我们想在一个画布上绘制多幅图,此时,可以使用 subplot 方法。但注意,subplot 会自动创建子图的画布,会覆盖、遮挡低层画布绘制的图像。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) plt.subplot(1 , 1 , 1 , facecolor="red" ) plt.plot(np.sin(x)) plt.subplot( 2 , 2 , 1 , facecolor="cyan" ) plt.plot(np.sin(x)) plt.subplot(2 , 2 , 2 , facecolor="red" ) plt.plot(np.sin(x)) plt.subplot(2 , 2 , 3 , facecolor="blue" ) plt.plot(np.sin(x)) plt.subplot(2 , 2 , 4 , facecolor="yellow" ) plt.plot(np.sin(x)) plt.subplot(2 , 1 , 2 , facecolor="orange" ) plt.plot(np.tan(x)) plt.show()
Matplotlib add_subplot 绘多幅图-堆叠 subplot 方法会用高层画布完全遮挡低层画布,包括低层画布的坐标刻度等信息。如果我们不想遮挡低层画布的未被高层画布覆盖的区域,可以使用 add_subplot 方法,它只遮挡绘图区,甚至低层画布的坐标轴刻度仍能保留下来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig = plt.figure() ax1 = fig.add_subplot(111 , facecolor="y" ) ax1.plot(np.sin(x)) ax2 = fig.add_subplot(221 , facecolor="c" ) ax2.plot(np.sin(x)) ax3 = fig.add_subplot(222 , facecolor="b" ) ax3.plot(np.cos(x)) ax4 = fig.add_subplot(212 , facecolor="orange" ) ax4.plot(np.tan(x)) plt.show()
并排画多张图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig = plt.figure() ax1 = fig.add_subplot(221 , facecolor="y" ) ax1.plot(np.sin(x)) ax2 = fig.add_subplot(222 , facecolor="c" ) ax2.plot(np.sin(x)) ax3 = fig.add_subplot(223 , facecolor="b" ) ax3.plot(np.cos(x)) ax4 = fig.add_subplot(224 , facecolor="orange" ) ax4.plot(np.tan(x)) plt.show()
Matplotlib add_axes 绘多幅图-堆叠在任意区域 add_axes 绘图类似于 add_subplot,但能画在低层画布的任何区域,灵活性更好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig = plt.figure(facecolor="g" ) ax1 = fig.add_axes([0.1 , 0.1 , 0.8 , 0.8 ], facecolor="c" ) ax2 = fig.add_axes([0.4 , 0.35 , 0.3 , 0.3 ], facecolor="y" ) ax1.plot(x, np.sin(x), "b" ) ax2.plot(x, np.cos(x), "r" ) ax1.set_title("正弦曲线" ) ax2.set_title("余弦曲线" ) ax2.text(0.5 , 0.5 , "我是余弦曲线的标识" , transform=ax2.transAxes) plt.show()
取消坐标轴
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig = plt.figure(facecolor="g" ) ax1 = fig.add_axes([0.1 , 0.1 , 0.8 , 0.8 ], facecolor="c" ) ax2 = fig.add_axes([0.4 , 0.35 , 0.3 , 0.3 ], facecolor="y" ) ax1.plot(x, np.sin(x), "b" ) ax2.plot(x, np.cos(x), "r" ) ax1.set_title("正弦曲线" ) ax2.set_title("余弦曲线" ) ax2.text(0.5 , 0.5 , "我是余弦曲线的标识" , transform=ax2.transAxes) ax2.axis("off" ) plt.show()
Matplotlib subplots 绘多幅图-均匀分布 使用 add_subplot 能够画多幅图,但如果索引指定不好,可能会造成绘图区覆盖情况。使用 subplots 能够很好地进行并排图像绘画。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig, ax = plt.subplots(2 , 2 ) ax[0 ][0 ].plot(x, np.sin(x)) ax[0 ][0 ].set_title("正弦曲线" ) ax[0 ][1 ].plot(x, np.cos(x)) ax[0 ][1 ].set_title("余弦曲线" ) ax[1 ][0 ].plot(x, np.tan(x)) ax[1 ][0 ].set_title("正切曲线" ) ax[1 ][1 ].plot(x, np.tanh(x)) ax[1 ][1 ].set_title("双曲正切曲线" ) plt.show()
可以看到上图像的横坐标刻度和下图像的标题遮挡,可以使用如下的两种方法处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig, ax = plt.subplots(2 , 2 ) ax[0 ][0 ].plot(x, np.sin(x)) ax[0 ][0 ].set_title("正弦曲线" ) ax[0 ][1 ].plot(x, np.cos(x)) ax[0 ][1 ].set_title("余弦曲线" ) ax[1 ][0 ].plot(x, np.tan(x)) ax[1 ][0 ].set_title("正切曲线" ) ax[1 ][1 ].plot(x, np.tanh(x)) ax[1 ][1 ].set_title("双曲正切曲线" ) fig.tight_layout() plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import matplotlib.pyplot as pltimport numpy as npx = np.linspace(-5 , 5 , 101 ) fig, ax = plt.subplots(2 , 2 ) ax[0 ][0 ].plot(x, np.sin(x)) ax[0 ][0 ].set_title("正弦曲线" ) ax[0 ][1 ].plot(x, np.cos(x)) ax[0 ][1 ].set_title("余弦曲线" ) ax[1 ][0 ].plot(x, np.tan(x)) ax[1 ][0 ].set_title("正切曲线" ) ax[1 ][1 ].plot(x, np.tanh(x)) ax[1 ][1 ].set_title("双曲正切曲线" ) plt.subplots_adjust(wspace=0.2 , hspace=0.5 ) plt.show()
Matplotlib subplot2grid 绘多幅图-不均匀划分 subplots 绘多幅图是均匀划分画布,如果想要不均匀划分,想把某些图占用更多的画布,可以采用 subplot2grid 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import matplotlib.pyplot as pltimport numpy as npax1 = plt.subplot2grid((3 , 3 ), (0 , 0 ), colspan=2 ) ax2 = plt.subplot2grid((3 , 3 ), (0 , 2 ), rowspan=3 ) ax3 = plt.subplot2grid((3 , 3 ), (1 , 0 ), rowspan=2 , colspan=2 ) x = np.linspace(-5 , 5 , 101 ) ax1.plot(x, np.sin(x)) ax1.set_title(r"$\sin$" ) ax2.plot(x, np.cos(x)) ax2.set_title(r"$\cos$" ) ax2.grid(color="r" , ls="-." , lw=0.25 ) ax3.plot(x, np.tan(x)) ax3.set_title(r"$\tan$" ) plt.tight_layout() plt.show()
3D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimport numpy as npfrom mpl_toolkits import mplot3dfig = plt.figure() ax = plt.axes(projection="3d" ) z = np.linspace(0 , 1 , 100 ) x = z * np.sin(20 * z) y = z * np.cos(20 * z) c = x + y ax.scatter3D(x, y, z, c=c) ax.set_title("3d Scatter plot" ) plt.show()
字体大小调整 所有字体统一调整:
1 2 3 4 5 6 7 8 9 10 11 12 import matplotlibfont = {'weight' : 'bold' , 'size' : 22 } matplotlib.rc('font' , **font) matplotlib.rcParams.update({'font.size' : 22 }) import matplotlib.pyplot as pltplt.rcParams.update({'font.size' : 22 })
所有可调整的属性见 Customizing matplotlib page
单个对象字体设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import matplotlib.pyplot as pltSMALL_SIZE = 8 MEDIUM_SIZE = 10 BIGGER_SIZE = 12 plt.rc('font' , size=SMALL_SIZE) plt.rc('axes' , titlesize=SMALL_SIZE) plt.rc('axes' , labelsize=MEDIUM_SIZE) plt.rc('xtick' , labelsize=SMALL_SIZE) plt.rc('ytick' , labelsize=SMALL_SIZE) plt.rc('legend' , fontsize=SMALL_SIZE) plt.rc('figure' , titlesize=BIGGER_SIZE) import matplotlibSMALL_SIZE = 8 matplotlib.rc('font' , size=SMALL_SIZE) matplotlib.rc('axes' , titlesize=SMALL_SIZE)
参考文献
Matplotlib教程(非常详细)