Matplotlib 是创建在 NumPy 数组基础上的多平台数据可视化程序库,能够画出相似 MATLAB 风格的交互式图形。
Matplotlib 最重要的特性之一就是具备良好的操做系统兼容性和图形显示底层接口兼容性(graphics backend)。Matplotlib 支持几十种图形显示接口与输出格式,这使得用户不管在哪一种操做系统上均可以输出本身想要的图形格式。这种跨平台、面面俱到的特色已经成为Matplotlib 最强大的功能之一,atplotlib 也所以吸引了大量用户,进而造成了一个活跃的开发者团队,晋升为 Python 科学领域不可或缺的强大武器。python
import matplotlib as mpl import matplotlib.pyplot as plt
使用 plt.style 来选择图形的绘图风格。例如:shell
plt.style.use('classic')
若是在一个脚本文件中使用 Matplotlib,那么显示图形的时候必须使用 plt.show()。plt.show() 会启动一个事件循环(event loop),并找到全部当前可用的图形对象,而后打开一个或多个交互式窗口显示图形。canvas
须要注意的是:一个 Python 会话(session)中只能使用一次 plt.show(),所以一般都把它放在脚本的最后。多个 plt.show() 命令会致使难以预料的显示异常,应该尽可能避免。数组
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))
plt.show()
在 IPython shell 中交互式地使用 Matplotlib 画图很是方便,在IPython 启动 Matplotlib 模式就可使用它。为了启用这个模式,须要在启动 ipython 后使用 %matplotlib 魔法命令:session
此后的任何 plt 命令都会自动打开一个图形窗口,增长新的命令,图形就会更新。dom
有一些变化(例如改变已经画好的线条属性)不会自动及时更新;对于这些变化,可使用plt.draw() 强制更新。在 IPython shell 中启动 Matplotlib 模式以后,就不须要使用 plt.show() 了。ide
使用 savefig() 命令能够将图形保存为文件。svg
x = np.linspace(0, 10, 100) fig = plt.figure() plt.plot(x, np.sin(x)) plt.plot(x, np.cos(x)) fig.savefig('my_figure.png')
以上代码将图形以png格式保存在目录下。函数
经过 canvas 对象的方法能够查看系统支持的文件格式。工具
fig.canvas.get_supported_filetypes()
{'ps': 'Postscript', 'eps': 'Encapsulated Postscript', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'jpg': 'Joint Photographic Experts Group', 'jpeg': 'Joint Photographic Experts Group', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format'}
Matplotlib 有一个容易让人混淆的特性,就是它的两种画图接口:一个是便捷的MATLAB 风格接口,另外一个是功能更强大的面向对象接口。
Matplotlib 最初做为 MATLAB 用户的 Python 替 代 品, 许 多 语 法 都 和 MATLAB 类 似。MATLAB 风格的工具位于 pyplot(plt)接口中。下面是典型的 Matlab 风格的代码。
plt.figure() # 建立图形 # 建立两个子图中的第一个,设置坐标轴 plt.subplot(2, 1, 1) # (行、列、子图编号) plt.plot(x, np.sin(x)) # 建立两个子图中的第二个,设置坐标轴 plt.subplot(2, 1, 2) plt.plot(x, np.cos(x))
这种接口最重要的特性是有状态的(stateful):它会持续跟踪“当前的”图形和坐标轴,全部 plt 命令均可以应用。使用 plt.gcf()(获取当前图形)和 plt.gca()(获取当前坐标轴)能够查看具体信息。
# 先建立图形网格 # ax是一个包含两个Axes对象的数组 fig, ax = plt.subplots(2) # 在每一个对象上调用plot()方法 ax[0].plot(x, np.sin(x)) ax[1].plot(x, np.cos(x))
plt.style.use('seaborn-whitegrid') # 建立一个图形 fig 和一个坐标轴 ax fig = plt.figure() ax = plt.axes()
在 Matplotlib 里面,figure(plt.Figure 类的一个实例)能够被当作是一个可以容纳各类坐标轴、图形、文字和标签的容器。axes(plt.Axes 类的一个实例)是一个带有刻度和标签的矩形,最终会包含全部可视化的图形元素。
建立好坐标轴以后,就能够用 ax.plot 画图了。若是想在一张图中建立多条线,能够重复调用 plot 命令。
plt.plot() 函数能够经过相应的参数设置颜色与风格。要修改颜色,就可使用 color 参数,它支持各类颜色值的字符串。
x= np.linspace(0, 10, 100) plt.plot(x, np.sin(x - 0), color='blue') # 标准颜色名称 plt.plot(x, np.sin(x - 1), color='g') # 缩写颜色代码(rgbcmyk) plt.plot(x, np.sin(x - 2), color='0.75') # 范围在0~1的灰度值 plt.plot(x, np.sin(x - 3), color='#FFDD44') # 十六进制(RRGGBB,00~FF) plt.plot(x, np.sin(x - 4), color=(1.0,0.2,0.3)) # RGB元组,范围在0~1 plt.plot(x, np.sin(x - 5), color='chartreuse'); # HTML颜色名称
若是不指定颜色,Matplotlib 就会为多条线自动循环使用一组默认的颜色。
与之相似,你也能够用 linestyle 调整线条的风格。
plt.plot(x, x + 0, linestyle='solid') plt.plot(x, x + 1, linestyle='dashed') plt.plot(x, x + 2, linestyle='dashdot') plt.plot(x, x + 3, linestyle='dotted'); # 你能够用下面的简写形式 plt.plot(x, x + 4, linestyle='-') # 实线 plt.plot(x, x + 5, linestyle='--') # 虚线 plt.plot(x, x + 6, linestyle='-.') # 点划线 plt.plot(x, x + 7, linestyle=':'); # 实点线
一种更简洁的方式是将 linestyle 和 color 编码组合起来。
plt.plot(x, x + 0, '-g') # 绿色实线 plt.plot(x, x + 1, '--c') # 青色虚线 plt.plot(x, x + 2, '-.k') # 黑色点划线 plt.plot(x, x + 3, ':r'); # 红色实点线
调整坐标轴上下限最基础的方法是 plt.xlim() 和 plt.ylim()。
plt.plot(x, np.sin(x)) plt.xlim(-1, 11) plt.ylim(-1.5, 1.5);
还有一个方法是 plt.axis()(注意不要搞混 axes 和 axis)。经过传入 [xmin, xmax, ymin, ymax] 对应的值。
plt.plot(x, np.sin(x))
plt.axis([-1, 11, -1.5, 1.5])
plt.plot(x, np.sin(x)) plt.title("A Sine Curve") plt.xlabel("x") plt.ylabel("sin(x)")
Matplotlib 内置了一个简单快速的方法,能够用来建立图例,即plt.legend()。在 plt.plot 函数中用 label 参数为每条线设置一个标签更加简单。
plt.plot(x, np.sin(x), '-g', label='sin(x)') plt.plot(x, np.cos(x), ':b', label='cos(x)') plt.legend()
一些 MATLAB 风格的方法和面向对象方法的转换以下所示:
在用面向对象接口画图时,不须要单独调用这些函数,一般采用 ax.set() 方法一次性设置全部的属性是更简便的方法。
ax = plt.axes() ax.plot(x, np.sin(x)) ax.set(xlim=(0, 10), ylim=(-2, 2), \ xlabel='x', ylabel='sin(x)', \ title='A Simple Plot')
x = np.linspace(0, 10, 30) y = np.sin(x) plt.plot(x, y, 'o', color='black')
部分图形标记展现以下:
rng = np.random.RandomState(0) for marker in ['o', '.', ',', 'x', '+', 'v', '^', '<', '>', 's', 'd']: plt.plot(rng.rand(5), rng.rand(5), marker, \ label="marker='{0}'".format(marker)) plt.legend(numpoints=1) plt.xlim(0, 1.8)
plt.plot(x, y, '-or'); # 直线(-)、圆圈(o)、红色(r)
这些标记还能够与线条、颜色代码组合起来,画出一条链接散点的线。
plt.plot支持许多设置线条和散点属性的参数,例如:
plt.plot(x, y, '-p', color='b', \ markersize=15, linewidth=4, \ markerfacecolor='w', \ markeredgecolor='r', \ markeredgewidth=2)
plt.scatter 与 plt.plot 的主要差异在于,前者在建立散点图时具备更高的灵活性,能够单独控制每一个散点与数据匹配,也可让每一个散点具备不一样的属性(大小、表面颜色、边框颜色等)。
rng = np.random.RandomState(0) x = rng.randn(100) y = rng.randn(100) colors = rng.rand(100) sizes = 300 * rng.rand(100) plt.scatter(x, y, c=colors, s=sizes, \ alpha=0.3, cmap='viridis') plt.colorbar() # 显示颜色条
能够用 Scikit-Learn 程序库里面的鸢尾花(iris)数据来演示。
from sklearn.datasets import load_iris iris = load_iris() features = iris.data.T plt.scatter(features[0], features[1], alpha=0.3, \ s=100*features[3], c=iris.target, cmap='viridis') plt.xlabel(iris.feature_names[0]) plt.ylabel(iris.feature_names[1])
每一个点的坐标值 (x, y) 分别表示花萼的长度和宽度,而点的大小表示花瓣的宽度,三种颜色对应三种不一样类型的鸢尾花。
看到熟悉的iris忍不住和ggplot2对比一下,ggplot做图以下:
library(ggplot2) ggplot(data=iris,aes(Sepal.Length,Sepal.Width, size=Petal.Width, colour=Species,alpha=I(0.3)))+ geom_point()+guides(colour=F,size=F)+ labs(x="sepal length(cm)",y="sepal width(cm)")+ theme_light()+theme(axis.title.x= element_text(size = 10), axis.title.y= element_text(size = 10))
iris.feature_names
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
iris.data.shape
(150, 4)
iris.data是150行4列的数据矩阵,T表示转置。
plt.plot 与 plt.scatter 在数据量较小的时候,效率上的差别不大。可是当数据变大到几千个散点时,plt.plot 的效率将大大高于 plt.scatter。这是因为 plt.scatter 会对每一个散点进行单独的大小与颜色的渲染,所以渲染器会消耗更多的资源。
x = np.linspace(0, 10, 50) dy = 0.8 y = np.sin(x) + dy * np.random.randn(50) plt.errorbar(x, y, yerr=dy, fmt='.k')
plt.errorbar(x, y, yerr=dy, fmt='o', color='black', \ ecolor='lightgray', elinewidth=3, capsize=0)
Scikit-Learn 程序库 API 里面有一个简单的高斯过程回归方法(Gaussian process regression,GPR),这是用一种很是灵活的非参数方程(nonparametric function)对带有不肯定性的连续测量值进行拟合的方法。
能够经过区域填充表示连续偏差。
from sklearn.gaussian_process import GaussianProcessRegressor from sklearn.gaussian_process.kernels import ConstantKernel, RBF # 定义模型和要画的数据 kernel = ConstantKernel(constant_value=0.2, \ constant_value_bounds=(1e-4, 1e4)) * RBF(length_scale=0.5, \ length_scale_bounds=(1e-4, 1e4)) gpr = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=2) model = lambda x: x * np.sin(x) xdata = np.array([1, 3, 5, 6, 8]).reshape(-1, 1) ydata = model(xdata) # 计算高斯过程拟合结果 gpr.fit(xdata, ydata) xfit = np.linspace(0, 10, 1000).reshape(-1, 1) mu, cov = gpr.predict(xfit, return_cov=True) yfit = mu.ravel() dyfit = 1.96 * np.sqrt(np.diag(cov))# 95%置信区间 # 将结果可视化 xfit = xfit.ravel() plt.plot(xdata, ydata, 'or') plt.plot(xfit, yfit, '-', color='gray') plt.fill_between(xfit.ravel(), yfit - dyfit, yfit + dyfit, \ color='gray', alpha=0.2) plt.xlim(0, 10)
从结果图形中能够很是直观地看出高斯过程回归方法拟合的效果:在接近样本点的区域,模型受到很强的约束,拟合偏差很是小,很是接近真实值;而在远离样本点的区域,模型不受约束,偏差不断增大。
用 plt.contour 画等高线图、用 plt.contourf 画带有填充色的等高线图(filled contour plot)的色彩、用 plt.imshow 显示图形。
def f(x, y): return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x) x = np.linspace(0, 5, 50) y = np.linspace(0, 5, 40) X, Y = np.meshgrid(x, y) Z = f(X, Y) plt.contour(X, Y, Z, colors='black')
当图形中只使用一种颜色时,默认使用虚线表示负数,使用实线表示正数。
plt.contour(X, Y, Z, 20, cmap='Set1')
在 IPython 里使用 plt.cm.<TAB> 浏览 Matplotlib 中的配色方案。
使用 plt.imshow()能够将二维数组渲染成渐变图。
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', \ cmap='Set1') plt.colorbar() plt.axis(aspect='image')
还有一个可能会用到的方法,就是将等高线图与彩色图组合起来。首先须要用一幅背景色半透明的彩色图,与另外一幅坐标轴相同、带数据标签的等高线图叠放在一块儿。
contours = plt.contour(X, Y, Z, 3, colors='black') plt.clabel(contours, inline=True, fontsize=8) plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', \ cmap='Set1', alpha=0.5) plt.colorbar()