使用 Matplotlib 生成数据图
Matplotlib 是一个非常优秀的 Python 2D 绘图库,只要给出符合格式的数据,通过 Matplotlib 就可以方便地制作折线图,柱状图,散点图等各种高质量的数据图
安装 Matplotlib 包
pip install matplotlib
安装完成后 通过 pydoc 来查看 Matplotilb 包的文档,命令行窗口运行
python -m pydoc -p 8899
运行命令之后,打开浏览器查看 http://localhost:8899/ 页面
Matplotlib 数据图入门(简单折线图)
简单折线图
import matplotlib.pyplot as plt
# 定义两个列表分别作为 X轴,Y轴数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
# 第一个列表代表横坐标的值,第二个列表代表纵坐标的值
plt.plot(x_data, y_data)
plt.show() # 调用 show() 显示图形
如果在调用 plot() 函数时只传入一个 list 列表,该 list 列表的数据将作为 Y 轴数据,Matplotlib 会自动使用 0,1,2,3 作为 X 轴数据
使用默认的 X 轴数据
import matplotlib.pyplot as plt
# 定义两个列表分别作为 X轴,Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
# 第一个列表代表横坐标的值,第二个列表代表纵坐标的值
plt.plot(y_data)
plt.show() # 调用 show() 显示图形
plot() 函数除了支持创建具有单条折线的折线图,也支持创建包含多条折线的复式折线图
只要在调用 plot() 函数时传入多个分别代表 X 轴 和 Y 轴数据的 list 数据即可
import matplotlib.pyplot as plt
# 定义两个列表分别作为 X轴,Y轴数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 传入两组分别代表 X轴, Y轴数据的 list 列表
plt.plot(x_data, y_data, x_data, y_data2)
# 还可以通过多次调用 plot() 函数来生成多条折线图
# plt.plot(x_data, y_data)
# plt.plot(x_data, y_dy_data2ata)
plt.show() # 调用 show() 显示图形
调用 plot() 函数时还可以传入额外的参数来指定折线图的样子,如线宽,颜色,样式等
import matplotlib.pyplot as plt
# 定义两个列表分别作为 X轴,Y轴数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 传入两组分别代表 X轴, Y轴数据的 list 列表
plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--')
plt.plot(x_data, y_data2, color='blue', linewidth=3.0, linestyle='-.')
# 还可以通过多次调用 plot() 函数来生成多条折线图
# plt.plot(x_data, y_data)
# plt.plot(x_data, y_dy_data2ata)
plt.show() # 调用 show() 显示图形
管理图例(标签)
对于复试折线图来说,应该为每条折线图都添加图例,此时可通过 legend() 函数来实现
对于该函数可传入两个 list 参数
第一个 list(handles 参数)用于引用折线图上的每条折线
第二季 list(labels) 代表为每条折线所添加的图例
import matplotlib.pyplot as plt
# 定义两个列表分别作为 X轴,Y轴数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色,线宽和样式
ln1, = plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--')
ln2, = plt.plot(x_data, y_data2, color='blue', linewidth=3.0, linestyle='-.')
# 调用 legend() 函数设置图例
plt.legend(handles=[ln1, ln2], labels=['Android', 'Java'], loc='lower right')
plt.show() # 调用 show() 显示图形
loc参数支持指定图例的添加位置,该参数支持如下参数值
参数 | 描述 |
---|---|
‘best’ | 自动选择最佳位置 |
‘upper right’ | 将图例放在右上角 |
‘upper left’ | 将图例放在左上角 |
‘lower left’ | 将图例放在左下角 |
‘lower right’ | 将图例放在右下角 |
‘right’ | 将图例放在右边 |
‘center left’ | 将图例放在右边居中的位置 |
‘center right’ | 将图例放在右边居中的位置 |
‘lower center’ | 将图例放在底部居中的位置 |
‘upper center’ | 将图例放在顶部居中的位置 |
‘center’ | 将图例放在中心 |
Matplotlib 也允许在调用 plot() 函数时为每条折线分别传入 label 参数
程序在调用 legend() 函数时就无需传入 labels,handles 参数
import matplotlib.pyplot as plt
# 定义两个列表分别作为 X轴,Y轴数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色,线宽和样式
ln1, = plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--', label='Android')
ln2, = plt.plot(x_data, y_data2, color='blue', linewidth=3.0, linestyle='-.', label='Java')
# 调用 legend() 函数设置图例
plt.legend(loc='best')
plt.show() # 调用 show() 显示图形
管理坐标轴
可以调用 xlable() 和 ylabel() 函数分别设置 X 轴,Y 轴的名称,
也可以通过 title() 函数设置整个数据图的标题
还可以调用 xticks(),yticks() 函数分别改变 X轴,Y轴的刻度值(允许使用文本作为刻度值)
如下程序为数据添加了名称,标题和坐标轴刻度值
import matplotlib.pyplot as plt
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的 Y 轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线颜色,线宽和样式
plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--', label='Java')
plt.plot(x_data, y_data2, color='blue', linewidth=3.0, linestyle='-', label='Android')
plt.legend(loc='best')
# 设置两个坐标轴的名称
plt.xlabel("years")
plt.ylabel("sales")
# 设置数据图的标题
plt.title('Annual sales volume')
# 设置 Y 轴上的数值文本
# 第一个参数是点的位置,第二个参数是点的文字提示
plt.yticks([50000, 70000, 100000], ['Very good', 'excellent', 'Hot and explosive'])
plt.show()
如果要对 X 轴,Y 轴进行更细致的控制,则可调用 gca() 函数来获取坐标轴信息对象,然后对坐标轴进行控制
比如控制坐标轴上刻度值的位置和坐标轴的位置等
import matplotlib.pyplot as plt
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的 Y 轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线颜色,线宽和样式
plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--', label='Java')
plt.plot(x_data, y_data2, color='blue', linewidth=3.0, linestyle='-', label='Android')
plt.legend(loc='best')
# 设置两个坐标轴的名称
plt.xlabel("years")
plt.ylabel("sales")
# 设置数据图的标题
plt.title('Annual sales volume')
# 设置 Y 轴上的数值文本
# 第一个参数是点的位置,第二个参数是点的文字提示
plt.yticks([50000, 70000, 100000], ['Very good', 'excellent', 'Hot and explosive'])
ax = plt.gca()
# 设置将 X 轴的刻度值放在底部 X 轴上
ax.xaxis.set_ticks_position('bottom')
# 设置 Y 轴的刻度值放在左边 Y 轴上
ax.yaxis.set_ticks_position('left')
# 设置右边坐标轴的颜色(设置为 none 表示不显示)
ax.spines['right'].set_color('none')
# 设置顶部坐标轴线的颜色(设置为 none 表示不显示)
ax.spines['top'].set_color('none')
# 定义底部坐标轴线的位置(放在 7000 数值处)
ax.spines['bottom'].set_position(('data', 70000))
plt.show()
管理多个子图
Matplotlib 除可以生成包含多条折线的复式折线图之外,它还允许在一张数据图上包含多个子图
调用 subplot() 函数可以创建一个子图
程序就可以在子图上进行绘制
subplot(nrows, ncols,index, **kwargs) 函数
nrows 参数指定将数据图区域分成多少行
ncols 参数指定将数据图区域分成多少列
index 参数指定获取第几个区域
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
# 定义从 -pi 到 pi 之间的数据,平均 64 个数据点
x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)
# 将整个 figure 分成两行两列,第三个参数表示将该图形放在第 1 个网格中
plt.subplot(2, 2, 1)
# 绘制正弦曲线
plt.plot(x_data, np.sin(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Sine curve') # 正弦曲线
# 将整个 figure 分成两行两列,并将该图形放在第 2 个网格中
plt.subplot(222)
# 绘制余弦曲线
plt.plot(x_data, np.cos(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['right'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Cosine curve') # 余弦曲线
# 将整个 figure 分成两行两列,并将该图形放在第 3 个网格中
plt.subplot(223)
# 绘制正切曲线
plt.plot(x_data, np.tan(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['right'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Tangent curve') # 正切曲线
plt.show()
注意修改的位置
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
# 定义从 -pi 到 pi 之间的数据,平均 64 个数据点
x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)
# 将整个 figure 分成两行两列,第三个参数表示将该图形放在第 1 个网格中
plt.subplot(2, 1, 1) # 修改的位置
# 绘制正弦曲线
plt.plot(x_data, np.sin(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Sine curve') # 正弦曲线
# 将整个 figure 分成两行两列,并将该图形放在第 2 个网格中
plt.subplot(223) # 修改的位置
# 绘制余弦曲线
plt.plot(x_data, np.cos(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['right'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Cosine curve') # 余弦曲线
# 将整个 figure 分成两行两列,并将该图形放在第 3 个网格中
plt.subplot(224) # 修改的位置
# 绘制正切曲线
plt.plot(x_data, np.tan(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['right'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Tangent curve') # 正切曲线
plt.show()
功能丰富的数据图
饼状图
Matplotlib 提供 pie() 函数来绘制饼状图
import matplotlib.pyplot as plt
# 准备数据
data = [0.16881, 0.14966, 0.07471, 0.06992, 0.04762, 0.03541, 0.02925, 0.2411, 0.02316, 0.01409, 0.36326]
# 准备标签
labels = ['Java', 'C', 'C++', 'Pytho', 'Visual Basic .NET', 'C#', 'PHP', 'JavaScript', 'SQL', 'Assembly langugage','其他']
# 将排在第 4 位的语言(Python)分离出来
explode = [0, 0, 0, 0.3, 0, 0, 0, 0, 0, 0, 0]
# 使用自定义颜色
colors = ['red', 'pink', 'magenta', 'purple', 'orange']
# 将横,纵坐标轴标准化处理,保证饼图是一个正圆,否则位椭圆
plt.axes(aspect='equal')
# 控制 X轴 和 Y轴的范围(用于控制饼状图的圆心,半径)
plt.xlim(0, 8)
plt.ylim(0, 8)
# 绘制饼图
plt.pie(x=data, # 绘制数据
labels=labels, # 添加编程语言标签
explode=explode, # 突出显示 Python
colors=colors, # 设置饼图的自定义填充色
autopct='% .3f%%', # 设置百分比的格式,此处保留 3 位小数
pctdistance=0.8, # 设置百分比标签于圆心的距离
startangle=180, # 设置饼图的初始角度
center=(4, 4), # 设置饼图圆心(相当于 x轴 和 y轴的范围)
radius=3.8, # 设置饼图的半径(相当于 X轴 和 Y轴的范围)
counterclock=False, # 是否为逆时针方向,这里设置为顺时针方向
wedgeprops={'linewidth': 1, 'edgecolor': 'green'}, # 设置饼图内外边界的属性值
textprops={'fontsize': 12, 'color': 'black'}, # 设置文本属性标签
frame=1 # 是否显示饼图的圆圈,此处设置为显示
)
plt.xticks(())
plt.yticks(())
# 添加图形标题
plt.title('2018 年 8 月的编程语言指数排行榜')
# 显示图形
plt.show()
柱状图
使用 Matplotil 提供的 bar() 函数来绘制柱状图, 于 plot(0 函数类似
程序每次调用 bar() 函数时都会生成一组柱状图,(生成多次柱状图,可通过多次调用 bar() 函数来实现)
import matplotlib.pyplot as plt
import numpy as np
# 构建数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 62000, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 绘图
plt.bar(x=x_data, height=y_data, label='Java', color='steelblue', alpha=0.8)
plt.bar(x=x_data, height=y_data2, label='Android', color='indianred', alpha=0.8)
# 在柱状图上显示具体的数值,ha 参数控制水平对齐方式, va 参数控制垂直对齐方式
for x, y in enumerate(y_data):
plt.text(x, y + 100, '%s' % y, ha='center', va='bottom')
for x, y in enumerate(y_data2):
plt.text(x, y + 100, '%s' % y, ha='center', va='bottom')
# 设置标题
plt.title('Java and Android')
# 为两个坐标轴设置名称
plt.xlabel('year')
plt.ylabel('salesVolume')
# 显示图例
plt.legend()
plt.show()
将多个柱状的条柱并列显示
为了精确控制条柱的宽度,可以在调用 bar() 函数时传入 width 参数,这样可以更好地计算条柱的并列方式
import matplotlib.pyplot as plt
import numpy as np
# 构建数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 62000, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
bar_width = 0.3
# 将 X 轴数据改为使用 range(len(x_data)), 就是 0, 1, 2
plt.bar(x=range(len(x_data)), height=y_data, label='Java', color='steelblue', alpha=0.8, width=bar_width)
# 将 X 轴数据改为使用 np.arange(len(x_data))+bar_width
# 就是 bar_width, 1+bar_width, 2+bar_width... 这样就和第一个柱状图并列了
plt.bar(x=np.arange(len(x_data)) + bar_width, height=y_data2, label='Android', color='indianred', alpha=0.8, width=bar_width)
# 在柱状图上显示具体的数值,ha 参数控制水平对齐方式, va 参数控制垂直对齐方式
for x, y in enumerate(y_data):
plt.text(x, y + 100, '%s' % y, ha='center', va='bottom')
for x, y in enumerate(y_data2):
plt.text(x, y + 100, '%s' % y, ha='center', va='bottom')
# 设置标题
plt.title('Java and Android')
# 为两个坐标轴设置名称
plt.xlabel('year')
plt.ylabel('salesVolume')
# 显示图例
plt.legend()
plt.show()
水平柱状图
调用 Matplotlib 的 barh() 函数可以生成水平柱状图
barh() 函数的用法于 bar() 函数的用法基本一样,
调用 barh() 函数时使用 y 参数传入 Y 轴数据,使用 width 参数传入代表条柱宽度的数据
import matplotlib.pyplot as plt
import numpy as np
# 构建数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 62000, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
bar_width = 0.3
# 将 Y 轴数据改为使用 range(len(x_data)), 就是 0, 1, 2
plt.barh(y=range(len(x_data)), width=y_data, label='Java', color='steelblue', alpha=0.8, height=bar_width)
# 将 Y 轴数据改为使用 np.arange(len(x_data))+bar_width
# 就是 bar_width, 1+bar_width, 2+bar_width... 这样就和第一个柱状图并列了
plt.barh(y=np.arange(len(x_data)) + bar_width, width=y_data2, label='Android', color='indianred', alpha=0.8,
height=bar_width)
# 在柱状图上显示具体的数值,ha 参数控制水平对齐方式, va 参数控制垂直对齐方式
for x, y in enumerate(y_data):
plt.text(x + 5000, y - bar_width / 2, '%s' % x, ha='center', va='bottom')
for x, y in enumerate(y_data2):
plt.text(x + 5000, y + bar_width / 2, '%s' % x, ha='center', va='bottom')
# 设置标题
plt.title('Java and Android')
# 为两个坐标轴设置名称
plt.xlabel('year')
plt.ylabel('salesVolume')
# 显示图例
plt.legend()
plt.show()
散点图
散点图和折线图需要的数据非常相似,区别是折线图会将各个数据点连接起来
散点图则只是描绘各数据点,并不会将这些数据点连接起来
调用 Matplotib 的 scatter() 函数来绘制散点图,该函数支持如下常用参数
函数 | 描述 |
---|---|
x | 指定 X 轴数据 |
y | 指定 Y 轴数据 |
s | 指定散点的大小 |
c | 指定散点的颜色 |
alpha | 指定散点的透明度 |
linewidths | 指定散点边框线的宽度 |
edgecolors | 指定散点边框的颜色 |
marker | 指定散点图的样式,该参数支持 ‘.’(点标记), ‘,’(像素标记), ‘o’(圆形标记), ‘v’(向下三角标记), ‘^’(向上三角标记), ‘<’(向左三角标记), ‘>’(向右三角标记), ‘1’(向下三叉标记), ‘2’(向上三叉标记), ‘3’(向左三叉标记), ‘4’(向右三叉标记), ‘s’(正方形标记), ‘p’(五边形标记), ‘*’(星形标记), ‘h’(八边形标记), ‘H’(另一种八边形标记), ‘+’(加号标记), ‘x’(x 标记), ‘D’(棱形标记), ‘d’(尖棱形标记), ’ |
camp | 指定散点的颜色映射,会使用不同的颜色来区分散点的值 |
使用 scatter() 函数来绘制散点图
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
# 定义从 -pi 到 pi 之间的数据, 平均取 64 个数据点
x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)
# 将整个 figure 分成两行两列,第三个参数表示将该图形放在第一个网格中
# 沿着正弦曲线绘制散点图
plt.scatter(x_data, np.sin(x_data), c='purple', # 设置点颜色
s=50, # 设置点的半径
alpha=0.5, # 设置透明度
marker='p', # 设置使用五边形标记
linewidths=1, # 设置边框的宽度
edgecolors=['green', 'yellow'] # 设置边框的颜色
)
# 绘制第二个散点图(只包含一个起点),突出起点
plt.scatter(x_data[0], np.sin(x_data)[0], c='red', # 设置点的颜色
s=150, # 设置点的半径
alpha=1 # 设置透明度
)
# 绘制第三个散点图(只包含一个结束点)突出结束点
plt.scatter(x_data[63], np.sin(x_data)[63], c='black', s=150, alpha=1)
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('Sine Curve Scatter Plot') # 正弦曲线散点图
plt.show()
等高线图
等高线图需要的是三维数据,其中 X,Y 轴数据决定坐标点,还需要对应高度数据(相当于 Z 轴数据)来决定不同坐标点的高度
有了合适的数据后,程序调用 contour() 函数绘制等高线,调用 contourf() 函数为等高线图填充颜色
contour(), contourf() 函数可以指定如下常用参数
参数 | 描述 |
---|---|
X | 指定 X 轴数据 |
Y | 指定 Y 轴数据 |
Z | 指定 X, Y 坐标对应点的高度数据 |
colors | 指定不同高度的等高线的颜色 |
alpha | 指定等高线的透明度 |
cmap | 指定等高线的颜色映射,即自动使用不同的颜色来区分不同高度区域 |
linewidths | 指定等高线的宽度 |
linestyles | 指定等高线的样式 |
使用 contour(), contourf() 函数来绘制等高线图
import matplotlib.pyplot as plt
import numpy as np
delta = 0.025
# 生成代表 X 轴数据的列表
x = np.arange(-3.0, 3.0, delta)
# 生成代表 Y 轴数据的列表
y = np.arange(-2.0, 2.0, delta)
# 对 x,y 数据进行网格化
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X ** 2 - Y ** 2)
z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
# 计算 Z 轴数据(高度数据)
z = (Z1 - z2) * 2
# 为等高线图填充颜色, 16指定将等高线分为几部分
plt.contourf(x, y, z, 16, alpha=0.75, cmap='rainbow') # 使用颜色映射来区分不同高度的区域
# 绘制等高线
C = plt.contour(x, y, z, 16, colors='black', linewidth=0.5)
# 绘制等高线数据
plt.clabel(C, inline=True, fontsize=10)
# 去除坐标轴
plt.xticks(())
plt.yticks(())
# 设置标题
plt.title('Contour map') # 等高线图
# 为两个坐标轴设置名称
plt.xlabel('latitude') # 纬度
plt.ylabel('longitude') # 经度
plt.show()
3D 图形
绘制 3D 图形,需要调用 Axes3D 对象的 plot_surface() 方法来完成
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
flg = plt.figure(figsize=(12, 8))
ax = Axes3D(flg)
delta = 0.125
# 生成代表 X 轴数据的列表
x = np.arange(-3.0, 3.0, delta)
# 生成代表 Y 轴数据的列表
y = np.arange(-2.0, 2.0, delta)
# 对 x, y 数据进行网格化
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X ** 2 - Y ** 2)
Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
# 计算 Z 轴数据(高度数据)
Z = (Z1 - Z2) * 2
# 绘制 3D 图形
ax.plot_surface(X, Y, Z,
rstride=1, # rstride(row) 指定行的跨度
cstride=1, # cstride(column) 指定列的跨度
cmap=plt.get_cmap('rainbow') # 设置颜色映射
)
# 设置 z 轴范围
ax.set_zlim(-2, 2)
# 设置标题
plt.title('3D Photo')
plt.show()