matplotlib的8个常用操作
By 青衣极客 Blue Geek In 2019-09-18
如果不想购买matlab,又想制作出matlab风格的图,那就选择matplotlib。这是一个完全免费的python第三方库,几乎提供matlab中所有绘图操作的对应接口。学会了这一款第三库之后,就可以随心所欲地可视化数据,绝对是生产力的体现。
在notebook或者终端环境下,由于与普通环境下GUI的不同,需要进行一些特殊的设置。
import os
import sys
import math
import matplotlib
%matplotlib notebook
#%matplotlib inline
#%config InlineBackend.figure_format = 'retina'
import matplotlib.pyplot as plt
import numpy as np
1. 曲线图和子图
用matplotlib来可视化曲线大概是最常用的操作,而在一张图中显示多个子图也是必不可少的需求。下面就演示一个简单的曲线图和子图的绘制示例:
# 生成数据
X = np.linspace(0, 2*math.pi)
Y = np.sin(2*X)
Y2 = np.sin(2*X+1)
Y3 = np.sin(2*X) + 1
# 绘图ß
plt.figure(figsize=(9.6, 7.2))
plt.subplot(1, 3, 1) # 绘制子图1
plt.plot(X, Y, c='blue') # 绘制曲线图
plt.plot(X, Y2, c='red', linestyle='--')
plt.plot(X, Y3, c='green', linestyle=':')
plt.subplot(1, 3, 2) # 绘制子图2
plt.plot(X, Y2, c='red', linestyle='--')
plt.subplot(1, 3, 3) # 绘制子图3
plt.plot(X, Y3, c='green', linestyle=':')
plt.show()
<IPython.core.display.Javascript object>
2. 散点图、极坐标图
曲线图叠加散点图会让数据点的位置更加清晰,更能吸引观察者的注意。极坐标图也会在一些场合需要用到,这里一并演示一下。
# 创建数据
X = np.linspace(0, 2*math.pi)
Y = np.sin(2*X)
# 绘图
plt.figure(figsize=(9.6, 7.2))
plt.subplot(1, 2, 1)
plt.plot(X, Y, c='b') # 绘制曲线图
plt.scatter(X, Y, marker='o') # 绘制散点图
plt.subplot(1, 2, 2, projection='polar')
plt.polar(X, Y, c='red',linestyle='--') # 绘制极坐标图
plt.show()
<IPython.core.display.Javascript object>
3. 条形图、饼状图、直方图
在可视化统计数据时,条形图、饼状图、直方图是很直观的工具,无论在企业中还是在科研中,海量的数据总不可能一一看尽,而这是统计图就可以派上用场。
# 创建数据
X = np.arange(10)
Y = np.random.random((10))
# 绘图
plt.figure(figsize=(9.6, 7.2))
plt.subplot(2, 2, 1)
plt.bar(X, Y) # 绘制纵向条形图
plt.subplot(2, 2, 2)
plt.barh(X, Y) # 绘制横向条形图
plt.subplot(2, 2, 3)
plt.pie(Y) # 绘制饼状图
plt.subplot(2, 2, 4)
plt.hist(Y, 10) # 绘制直方图
plt.show()
<IPython.core.display.Javascript object>
4. 设置图的基本属性
为了让画出的图更加美观,或者想要更加清晰地表达自己的意思,这时就需要对图的属性进行修改。比如调整线的颜色和样式,添加图例以及坐标轴的说明,还可以添加注解等等。
# 生成数据
X = np.linspace(0, 2*math.pi)
Y = np.sin(2*X)
Y2 = np.sin(2*X+math.pi/2)
Y3 = np.sin(2*X) + 1
# 绘图
plt.figure(figsize=(12.6, 7.2))
# 绘制曲线图
plt.plot(X, Y, c='blue', marker='p') # 设置颜色和标记
plt.plot(X, Y2, c='red', linestyle='--', marker='^') # 设置颜色、标记和线型
plt.plot(X, Y3, c='green', linestyle=':', marker='s')
# 设置图的基本属性
min_X = X.min()
max_X = X.max()
min_Y = min(Y.min(), Y2.min(), Y3.min())
max_Y = max(Y.max(), Y2.max(), Y3.max())
plt.axis([X.min()-1, X.max()+1, min_Y-0.5, max_Y+0.5]) # 设置坐标轴范围
plt.xlabel('time(sec)') # 设置横轴标记
plt.ylabel('value(meter)') # 设置纵轴标记
# 设置横轴刻度
plt.xticks((0, math.pi/2, math.pi, 3*math.pi/2, 2*math.pi),
('$0$', '$\pi/2$', '$\pi$', '$3\pi/2$', '$2\pi$')) # latex格式的文本
# 设置纵轴刻度
plt.yticks((-1, -0.5, 0, 0.5, 1, 1.5, 2))
plt.legend(labels=['blue', 'red', 'green'], loc='best') # 设置图例
plt.title('Title of Figure') # 设置图的标题
# 设置注解
plt.annotate('$y=sin(2x)$', xy=(0, 0), xytext=(-0.5,-1),
arrowprops=dict(facecolor='yellow', shrink=1))
plt.annotate('$y=sin(2x + \pi / 2)$', xy=(math.pi*3/2, -1), xytext=(math.pi*9/10,-1),
arrowprops=dict(facecolor='yellow', shrink=1))
plt.annotate('$y=sin(2x)+1$', xy=(math.pi*5/4, 2), xytext=(math.pi*2/4,1.5),
arrowprops=dict(facecolor='yellow', shrink=1))
# 去掉边框
ax = plt.gca()
ax.spines['top'].set_color('none') # 去掉顶部边框
ax.spines['bottom'].set_color('none') # 去掉底部边框
ax.spines['left'].set_color('none') # 去掉左侧边框
ax.spines['right'].set_color('none') # 去掉右侧边框
plt.show()
<IPython.core.display.Javascript object>
5. 等高线
在处理地理数据或者温度数据时,常常需要画等高线,以明确一些影响的范围。matplotlib当然也提供了这种操作。
plt.figure(figsize=(9.6, 7.2))
X = np.linspace(0, 1, 100)
Y = np.linspace(0, 1, 100)
XX, YY = np.meshgrid(X, Y)
Z = X**2 - YY**2/20
plt.subplot(1,2,1)
plt.contourf(XX, YY, Z) # 带颜色填充的等高线
plt.subplot(1,2,2)
plt.contour(XX, YY, Z) # 不进行颜色填充的等高线
plt.show()
<IPython.core.display.Javascript object>
6. 3D图
对三维数据可视化的需求也是比较大的,比2d图多了一个维度自然表达也更加丰富。而且三维数据是我们能够直观视觉感受的最高维度,如果有更高维度的数据一般也是用各种方式简化到3d可视化。
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(9.6, 7.2))
ax = fig.gca(projection='3d')
X = np.linspace(-10, 10, 100)
Y = np.linspace(-10, 10, 100)
XX, YY = np.meshgrid(X, Y)
Z = X**2 - YY**2/20
ax.plot_surface(XX, YY, Z)
plt.show()
<IPython.core.display.Javascript object>
7. 次坐标
在一个坐标中画出两种标度的数据可以让对比更加鲜明,特别是对一些发生相关联变化的关键点捕捉更加准确。
#fig = plt.figure(figsize=(10.8, 7.2))
X = np.linspace(0, 2*np.pi, 100)
Y1 = np.cos(2*X)
Y2 = 3*np.sin(X)
# 生成次坐标
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
# 绘制两个坐标下的曲线
ax1.plot(X, Y1, c='red', marker='p')
ax2.plot(X, Y2, c='blue', marker='^')
# 设置坐标轴标记
ax1.set_xlabel('time(sec)')
ax1.set_ylabel('Height(m)', rotation=75)
ax2.set_ylabel('Length(m)', rotation=75)
plt.show()
<IPython.core.display.Javascript object>
8. 保存和读取图片文件
有时画出的图可能要插入到论文中,有时要放进PPT,或者会做到视频demo中,等等不一而足的任务需要将绘制的图保存到文件。matplotlib可以保存普通的点阵图,也可以保存矢量图。如果要提升点阵图的分辨率还可以增加dpi。这里只演示最简单的保存图片和载入图片。
# 创建数据
X = np.linspace(0, 2*math.pi)
Y = np.sin(2*X)
# 绘图
plt.figure(figsize=(9.6, 7.2))
plt.subplot(1, 2, 1)
plt.plot(X, Y, c='b') # 绘制曲线图
plt.scatter(X, Y, marker='o') # 绘制散点图
plt.subplot(1, 2, 2, projection='polar')
plt.polar(X, Y, c='red',linestyle='--') # 绘制极坐标图
# 将figure保存为图片, 如果需要更加高清的图片可以修改dpi
img_path = '../output/mpl.png'
plt.savefig(img_path, transparent=True)
# 读取图片
img = plt.imread(img_path)
plt.figure()
plt.imshow(img)
plt.show()
<IPython.core.display.Javascript object>
<IPython.core.display.Javascript object>
matplotlib实在是太庞大了,在一篇文章中很难穷尽,毕竟它的文档就有上千页。这里只把最常用的一些功能和操作演示出来,大家就可以感受到其功能之强大。后续还有用basemap+matplotlib来绘制地图数据的讨论帖子也会制作出来。总而言之,matplotlib这款第三方的免费可视化工具会让你分析数据的能力可以看见。
CHANGELOG
- 2020-04-07 添加解说文本

COMMENT
博客评论区功能由Github Issue提供,提交Issue时请以本文标题为话题。
"BG08-matplotlib的8个常用操作"