Matplotlib是一个综合的(comprehensive )、用于创建静态、动态和交互性可视化Python库。先来看看一个典型的使用这个库的一个例子:
import matplotlib.pyplot as plt import numpy as np x = np.arange(0, 4, 0.05) y = np.sin(x*np.pi) fig, ax = plt.subplots(figsize=(3,2), constrained_layout=True) ax.plot(x, y) ax.set_xlabel('t [s]') ax.set_ylabel('S [V]') ax.set_title('Sine wave') fig.set_facecolor('lightsteelblue') plt.show()
几乎所有的使用matplotlib都会使用到以下语句:
import matplotlib.pyplot as plt
它有什么作用?要讲清楚这个,得从import关键字说起。
一、import关键字导入库import语句用于导入其他文件的方法、变量和类,这其实就是C++里边的导入库的操作。不过Python里边叫做模块(Module)。搜索库是按照一定的顺序搜索的,一般Python搜索库的顺序如下:
第一种语法:import module_name
- sys.path 我们pip install的三方库一般都是在这里(print(sys.path)可以查看这个目录)
- 当前目录(也就是运行程序的时候所在的目录)
Tips:最好不要用import来引用当前目录的python文件,因为它可能会出错。
第二种语法:from package_name import module_name/variable_name
一般,我们把模块组成的几何称为包(package),搜索的顺序和第一种语法一样。
顺便提一下几种常见的用法:
- import module_name as alias别名,放置模块名过长或者冲突
- from module_name import function_name, variable_name, class_name部分导出模块函数类和变量
- 反斜杠\换行
例子:
from numpy import pi from numpy import deg2rad from numpy import rad2deg import matplotlib.pyplot # 表示从matplotlib库(其实是一个文件夹)输出pyplot模块 import numpy as np #二、matplotlin.pyplot是一个重要接口类
一般而言,matplotlib将会被安装在Python的Lib/site-packages/matplotlib文件夹中,库名与文件名一致。库中内容就是一些*.py文件或者加密的*.pyd文件,里面有一个重要的文件pyplot.py,这是我们使用matplotlib库的接口对象,通过调用这个对象的方法可完成:
- 调用可绘制对象的构造函数,并将其显示在当前figure中;如AxesFiguretextarrowgirdlegend
- 控制对象行为。如关闭Figure,重新绘制Figure,清空Figure clf,自适应数据 autoscale,标题titlexlimyscaleytick
- 读取imread图像,rcrc_contentrcdefaultsrgrids等配置相关
- 以指定方式绘制数据。如:plotquiverpiescatterstairsspecgramcontourimshowstackplot
面向对象或者面向过程。面向对象显式创建Figures和Axes,在新建的这两个对象上调用相应的方法;面向过程依赖的对象是pyplot,这将会自动创建和管理Figures和Axes,使用pyplot的方法而不是Figures和Axes的方法。
面向对象的绘制风格(OO-style)如下:
x = np.linspace(0, 2, 100) # Sample data. # 尽管这是一个面向对象的风格,但是我们仍然会使用pyplot来构造对象实例 fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained') ax.plot(x, x, label='linear') # Plot some data on the axes. ax.plot(x, x**2, label='quadratic') # Plot more data on the axes... ax.plot(x, x**3, label='cubic') # ... and some more. ax.set_xlabel('x label') # Add an x-label to the axes. ax.set_ylabel('y label') # Add a y-label to the axes. ax.set_title("Simple Plot") # Add a title to the axes. ax.legend(); # Add a legend.
下面是绘制的结果:
面向对象这种绘制方式可以直接对很多细节进行控制,如果你只是想简单画个图,那么可以使用面向过程的方式,Matplotlib的官方Demo混杂了两种风格方式,总的来说,推荐使用OO-style尤其是那种比较复杂的绘制。下面是面向过程的绘制方法:
import numpy as np import matplotlib.pyplot as plt x = np.arange(0, 5, 0.1) y = np.sin(x) plt.plot(x,y) # 自动帮你管理Figure和Axes对比项目 含义 返回值 subplot pyplot对象方法(清空后加入) Axes add_subplot figure的方法(直接加入) Axes 2.2 辅助函数
对于一些你需要反复使用的plot,推荐使用一下的特征函数:
def my_plotter(ax, data1, data2, param_dict): """ A helper function to make a graph. """ out = ax.plot(data1, data2, **param_dict) return out
定义了上述函数,绘制时能节省不少力气:
data1, data2, data3, data4 = np.random.randn(4, 100) # make 4 random data sets fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(5, 2.7)) my_plotter(ax1, data1, data2, {'marker': 'x'}) my_plotter(ax2, data3, data4, {'marker': 'o'});三、Styling Artists 样式设计师
大多数plotting方法在调用的时候都会提供Artists对象的一些选项,比如说plot的线形,线宽,除了直接在调用时给定选项,你还可以在之后调用set_linestyle进行设置:
fig, ax = plt.subplots(figsize=(5, 2.7)) x = np.arange(len(data1)) ax.plot(x, np.cumsum(data1), color='blue', linewidth=3, linestyle='--') l, = ax.plot(x, np.cumsum(data2), color='orange', linewidth=2) l.set_linestyle(':');
下面来看看都有哪些东西可以供设置:
3.1 颜色Matplotlib的颜色表示方式有多种,详细参考颜色教程。
fig, ax = plt.subplots(figsize=(5, 2.7)) ax.scatter(data1, data2, s=50, facecolor='C0', edgecolor='k');
从上面可以看出,就算对同散点,都能对点边缘和内部的颜色进行控制,非常灵活。
3.2 线宽Linewidths 线形linestyles 标记大小 markersizes默认情况下,线宽是可供打印的点(1pt=1/72inch=0.35mm),划出来的线(stroked line)可设置线性,具体可以参考Linestyles,标记的大小可以设置,具体含义取决于绘制的类型。
四、标签绘制 4.1 文本绘制我们可以往figure任意位置中绘制文本,方法是使用text,matplotlib有一些方法是设置特定文字到指定有特殊含义的区域,如:set_xlabelset_ylabelset_title等:
mu, sigma = 115, 15 x = mu + sigma * np.random.randn(10000) fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained') # the histogram of the data n, bins, patches = ax.hist(x, 50, density=1, facecolor='C0', alpha=0.75) ax.set_xlabel('Length [cm]') ax.set_ylabel('Probability') ax.set_title('Aardvark lengths\n (not really)') ax.text(75, .025, r'$\mu=115,\ \sigma=15$') ax.axis([55, 175, 0, 0.03]) ax.grid(True);4.2 使用数学表达式
Matplotlib可以绘制符合Tex语法的文本表达式。如:
ax.set_title(r'$\signma_i=15')
在字符串前加上r原始字符串,因为Matplotlib内置了Tex语法解析和布局引擎,使用上非常方便。
4.3 Annotations 注释、注解fig, ax = plt.subplots(figsize=(5, 2.7)) t = np.arange(0.0, 5.0, 0.01) s = np.cos(2 * np.pi * t) line, = ax.plot(t, s, lw=2) ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5), arrowprops=dict(facecolor='black', shrink=0.05)) ax.set_ylim(-2, 2);
fig, ax = plt.subplots(figsize=(5, 2.7)) ax.plot(np.arange(len(data1)), data1, label='data1') ax.plot(np.arange(len(data2)), data2, label='data2') ax.plot(np.arange(len(data3)), data3, 'd', label='data3') ax.legend();
有关于Legend的详细教程,见Legend Guide
每一个Axes都含有两个(或者三个)Axis对象。除了表示线性范围外,Matplotlib还可以表示log-scale,因为对数很常见,因此有一些直接的方法(如loglog semilogx semilogy)等,使用如下:
fig, axs = plt.subplots(1, 2, figsize=(5, 2.7), layout='constrained') xdata = np.arange(len(data1)) # make an ordinal for this data = 10**data1 axs[0].plot(xdata, data) axs[1].set_yscale('log') axs[1].plot(xdata, data);
matplotlib将会根据你设置的scale进行数据的绘制,tick将会被展示的非常合理。
在每个tick上面的文字是可以定制的,他可以通过tick_locator和formatter来控制,如下:
fig, axs = plt.subplots(2, 1, layout='constrained') axs[0].plot(xdata, data1) axs[0].set_title('Automatic ticks') axs[1].plot(xdata, data1) axs[1].set_xticks(np.arange(0, 100, 30), ['zero', '30', 'sixty', '90']) axs[1].set_yticks([-1.5, 0, 1.5]) # note that we don't need to specify labels axs[1].set_title('Manual ticks');
Matplotlib可以处理日期和字符串数组的数据,就和我们处理浮点数一样。对于一个日期:
fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained') dates = np.arange(np.datetime64('2021-11-15'), np.datetime64('2021-12-25'), np.timedelta64(1, 'h')) data = np.cumsum(np.random.randn(len(dates))) ax.plot(dates, data) cdf = mpl.dates.ConciseDateFormatter(ax.xaxis.get_major_locator()) ax.xaxis.set_major_formatter(cdf);
对于字符串:
fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained') categories = ['turnips', 'rutabaga', 'cucumber', 'pumpkins'] ax.bar(categories, np.random.rand(len(categories)));
2.2 可以处理的数据类型 绘制类的函数如plot,处理的数据可以是numpy.arraynumpy.ma.masked_array或者可以被numpy.asarray转换成numpy.array和numpy.ma.masked_array的数据。
[1] https://blog.csdn.net/dreaming_coder/article/details/110835351 [2] https://zhuanlan.zhihu.com/p/63143493 [3] https://matplotlib.org/stable/tutorials/introductory/usage.html