Matplotlib数据可视化实战
本章学习目标
(1)熟练掌握扩展库Matplotlib及其依赖库的安装方法。
(2)了解Matplotlib 的绘图一般过程。
(3)熟练掌握折线图的绘制与属性设置。
(4)熟练掌握散点图的绘制与属性设置。
(5)熟练掌握柱状图的绘制与属性设置。
(6)熟练掌握饼状图的绘制与属性设置。
(7)熟练掌握雷达图的绘制与属性设置。
(8)了解三维曲线、曲面的绘制与属性设置。
(9)熟练掌握绘图区域的切分与属性设置。
(10)熟练掌握图例属性的设置。
(11)熟练掌握坐标轴属性的设置。
(12)了解事件响应与处理机制的工作原理。
(13)了解图形填充的方法。
(14)了解保存绘图结果的方法。
PsxZW.indd 215 2023/5/30 14:27:41 

2162163.1 数据可视化库Matplotlib 基础
在扩展库Matplotlib 中有2 个最常用的绘图模块:pylab 和
pyplot。其中,pylab 中除了包含pyplot 模块中的函数,还包含了扩
展库NumPy 中的常用函数,可以直接通过pylab 进行调用,不需要再额
外导入NumPy。
使用pylab 或pyplot 绘图的一般过程为:首先生成、读入或计算得到数据,然后根
据实际需要绘制折线图、散点图、柱状图、饼状图、雷达图、箱线图、三维曲线/ 曲面以
及极坐标系图形,接下来设置坐标轴标签(使用matplotlib.pyplot 模块的xlabel()、
ylabel() 函数或轴域的set_xlabel()、set_ylabel() 方法)、坐标轴刻度(使用
matplotlib.pyplot 模块的xticks()、yticks() 函数或轴域的set_xticks()、set_ 
yticks() 方法、图例(可以使用matplotlib.pyplot 模块的legend() 函数或轴域的
同名方法)、标题(可以使用matplotlib.pyplot 模块的title()、suptitle() 函数
或轴域的set_title() 方法)等图形属性,最后显示或保存绘图结果。
每一种图形都有特定的应用场景,对于不同类型的数据和可视化要求,要选择最合适
类型的图形进行展示,不能生硬地套用某种图形。
Matplotlib 默认情况下无法直接显示中文字符。如果图形中需要显示中文字符,
可以使用import matplotlib.pyplot as plt 导入模块pyplot,然后查看plt. 
rcParams 字典的当前值并进行必要的修改,也可以通过pyplot 模块的xlabel()、
ylabel()、xticks()、yticks()、title() 等函数或轴域(也称子图)对象对应的方
法的fontproperties 参数对坐标轴标签、坐标轴刻度、标题单独进行设置;如果需要
设置图例中的中文字符字体可以通过legend()函数的prop 参数进行设置。
使用下面的代码可以查看所有的可用字体。
from matplotlib.font_manager import fontManager 
names = sorted([f.name for f in fontManager.ttflist]) 
for name in names: 
print(name) 
如果安装了新字体之后在自己的程序中仍无法使用,可以删除文件C:/Users/.../ 
.matplotlib/fontlist-v330.json,然后重新运行程序。
在进行可视化时,应尽量避免仅仅依赖于颜色不同来区分同一个图形中的多个线条、
柱或面片,还应借助于线型、线宽、端点符号、填充符号等属性来提高区分度。因为有时
不仅要在计算机上查看图形,可能还需要打印,但是并不能保证总是有彩色打印机,灰度
打印时颜色信息丢失后就很难区分不同颜色的线条、柱或面片了。
视频二维码:3.1 
PsxZW.indd 216 2023/5/30 14:27:49 

217 
同一组数据可以使用不同形式的图形进行可视化,既可以绘制折线图,也可以绘制柱
状图、散点图、饼状图等其他图形,具体采用哪种图形最终取决于客户的要求和应用场景,
确定之后调用相应的函数即可。
以二维直角坐标系为例,使用plot() 函数绘制折线图时,数据用来确定折线图上若
干采样点的x、y 坐标,使用直线段依次连接这些顶点,如果顶点足够密集则可以形成光
滑曲线。如果使用scatter() 函数绘制散点图,数据用来确定若干顶点的x、y 坐标,然
后在这些位置上绘制指定大小和颜色的散点符号。如果使用bar() 函数绘制柱状图,数
据用来确定若干柱的位置(x 坐标)和高度(y 坐标)。
绘制图形并设置外围属性之后可以调用pyplot 模块的show() 函数直接显示图形,
也可以使用savefig() 函数或图形对象的同名方法保存为图片文件。savefig() 函数完
整用法如下。
savefig(fname, *, dpi='figure', format=None, metadata=None, 
bbox_inches=None, pad_inches=0.1, facecolor='auto', 
edgecolor='auto', backend=None, **kwargs) 
savefig() 函数中参数的含义如表3-1 所示。
表3-1 savefig()函数中参数的含义
参数名称含义
fname 要保存的文件名
dpi 
图形的分辨率(dots per inch ,每英寸多少像素),例如96、300、600,如果不指
定则使用Python 安装目录下配置文件Lib\site-packages\matplotlib\mpl-data\ 
matplotlibrc 中savefig.dpi 的值
facecolor、
edgecolor 
设置图形的背景色和边框颜色,默认均为白色
format 
用来指定保存文件的类型和扩展名,可以设置为'png'、'pdf'、'ps'、'eps'、'svg' 
以及'jpeg' 、'jpg'、'tif'、'tiff' 等其他后端所支持的类型。如果不指定该参数,
则根据参数fname 字符串指定的文件扩展名来确定类型
transparent 
如果设置为True 则子图透明,如果此时没有设置facecolor 和edgecolor 则整个图
形也透明
bbox_inches 用来指定保存图形的哪一部分,如果设置为'tight' 则使用能够包围图形的最小边框
pad_inches 用来设置当bbox_inches='tight'时图形的内边距
bbox_extra_ 
artists 
用来指定当bbox_inches='tight'时应考虑保存的额外图形元素
Matplotlib 绘制图形有很多种样式和风格,下面代码列出了所有可用的样式。
>>> import matplotlib.pyplot as plt 
>>> plt.style.available # 查看所有可用的图形样式
['bmh', 'classic', 'dark_background', 'fivethirtyeight', 'ggplot', 'grayscale', 
'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark-palette', 'seaborn-dark', 
PsxZW.indd 217 2023/5/30 14:27:55 

218218 
'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 
'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 
'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'seaborn'] 
下面的代码演示了如何指定图形样式,图3-1 和图3-2 分别演示了默认样式和
fivethirtyeight 两种样式的效果,其他样式可以自行测试。
import numpy as np 
import matplotlib.pyplot as plt 
# 指定图形样式
plt.style.use('fivethirtyeight') 
x = np.arange(0, 7, 0.01) 
y = np.sin(x) 
plt.plot(x, y) 
plt.show() 
图3-1 默认样式显示效果
图3-2 fivethirtyeight 样式显示效果
PsxZW.indd 218 2023/5/30 14:27:57 

219 
3.2 绘制折线图
pyplot 模块中的函数plot() 或者子图对象的同名方法用来绘制折线图,也可以同
时或单独绘制采样点,返回包含折线图的列表。完整语法如下。
plot(*args, scalex=True, scaley=True, data=None, **kwargs) 
可能的调用形式如下。
plot([x], y, [fmt], *, data=None, **kwargs) 
plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) 
其中,参数x、y 用来设置采样点坐标;参数fmt 用来设置颜色、线型、端点符号,格
式为'[marker][line][color]' 或'[color][marker][line]' ,例如'ro'、'go-'、
'rs'。其他常用的参数还有color/c、alpha、label、linestyle/ls、linewidth/ 
lw、marker、markeredgecolor/mec、markeredgewidth/mew、markerfacecolor/ 
mfc、markersize、pickradius、snap 等。可使用help(plt.plot) 查看完整用法和
参数含义,其中marker和ls参数使用较多,ls参数的值可以为'-'(表示实心线)、'--'(表
示短画线)、'-.'(表示点画线)、':'(表示点线),marker 参数可能的值与含义如表3-2 
所示。
表3-2 marker 参数取值范围与含义
字符含义字符含义
. 点, 像素
o 圆v 向下的三角形
^ 向上的三角形< 向左的三角形
> 向右的三角形* 星形
1 向下的三尖形2 向上的三尖形
3 向左的三尖形4 向右的三尖形
8 八边形s 正方形
p 五边形P 粗加号
h 1号六边形H 2 号六边形
+ 加号x 叉号
X 填充的叉号d 细金刚石
D 金刚石_ 横线
| 竖线
使用下面的代码可以绘制不同marker 参数的散点图,显示效果如图3-3 所示。
PsxZW.indd 219 2023/5/30 14:27:57 

import numpy as np 
import matplotlib.pyplot as plt 

markers = '.,ov^<>*12348spPhH+xXdD_|' 

x, y = np.mgrid[1:10:5j, 1:10:5j] 

for x_pos, y_pos, marker in zip(x.flatten(), y.flatten(), markers): 
plt.scatter(x_pos, y_pos, marker=marker, s=100) 
plt.text(x_pos+0.2, y_pos-0.2, s=repr(marker)) 

plt.axis('off') 

plt.show() 


图3-3 marker 参数不同取值的显示效果

例3-1 绘制带有中文标题、坐标轴标签和图例的正弦、余弦图像。运行结果如图3-4 
所示。

import matplotlib.pylab as pl 

t = pl.arange(0.0, 2.0*pl.pi, 0.01) # 自变量取值范围
s = pl.sin(t) # 计算正弦函数值
z = pl.cos(t) # 计算余弦函数值
视频二维码:例3-1 
pl.plot(t, # 采样点x轴坐标

 
s, # 采样点y轴坐标 
label='正弦', # 标签 
color='red') # 红色

pl.plot(t, z, label='余弦'
, 
lw=3, ls='--', color='blue') # 3 像素宽,虚线,蓝
色


pl.xlabel('x-变量', # 标签文
本 
fontproperties='STKAITI', # 字
体 
fontsize=18) # 字
号


pl.ylabel('y-正弦余弦函数值', fontproperties='simhei', fontsize=18) 

220 

PsxZW.indd 220 


2023/5/30 14:27:58 


221 
pl.title('sin-cos函数图像', # 标题文本 
fontproperties='STLITI', # 字体 
fontsize=24) # 字号
pl.legend(prop='STKAITI') # 创建图例,自动提取图形的线性、颜色、标签等属性
pl.grid(alpha=0.7, ls='-.') # 半透明网格线,点画线
pl.show() # 显示绘制的结果图像
图3-4 例3-1程序运行结果
例3-2 在绘图结果中添加水平线和垂直线。运行结果如图3-5 所示。
import numpy as np 
import matplotlib.pyplot as plt 
x = np.linspace(0, 2*np.pi, 100) 
y = np.sin(x) 
plt.plot(x, y, 'r-', lw=2, label='sin') # 绘制正弦曲线
# 在纵坐标-0.5 和0.5 处绘制两条水平直线,蓝色虚线
plt.axhline(-0.5, color='blue', ls='--', label='axhline') 
plt.axhline(0.5, color='blue', ls='--') 
# 在横坐标绘制垂直直线,绿色点画线
plt.axvline(np.pi, color='green', ls='-.', label='axvline') 
# 设置y 轴刻度位置和文本
plt.yticks([-1, -0.5, 0, 0.5, 1], ['-1', 'axhline', '0', 'axhline', '1']) 
plt.legend() 
plt.show() 
视频二维码:例3-2 
PsxZW.indd 221 2023/5/30 14:27:59 

222222
图3-5 例3-2程序运行结果
例3-3 绘制螺旋线,只绘制采样点。运行结果如图3-6所示。
import numpy as np 
import matplotlib.pyplot as plt 
theta = np.arange(0, 8*np.pi, 0.1) # 4 个圆周的角度,单位为弧度
r = np.arange(20, 20+len(theta)) 
plt.plot(r*np.cos(theta), r*np.sin(theta), 'ro') # 在采样点位置处绘制红色圆圈
plt.show() 
图3-6 例3-3程序运行结果
视频二维码:例3-3 
PsxZW.indd 222 2023/5/30 15:41:01 

223 
例3-4 同时绘制多条折线。运行结果如图3-7所示。
import numpy as np 
import matplotlib.pyplot as plt 
x = range(10) 
y = np.random.randint(20, 50, (10,3)) # 10行3 列位于[20,50) 区间的随机数
plt.plot(x, y, label=['a','b','c']) # 绘制3条折线图,每列数据对应一条折线图
plt.legend() 
plt.show() 
图3-7 例3-4程序运行结果
例3-5 同时绘制多条曲线。运行结果如图3-8所示。
图3-8 例3-5程序运行结果
视频二维码:例3-4 
PsxZW.indd 223 2023/5/30 14:28:03 

import numpy as np 
import matplotlib.pyplot as plt 


x1 = np.arange(0, 2*np.pi, 0.01) 视频二维码:例3-
5
y1 = np.sin(x1)
x2 = np.arange(2*np.pi, 4*np.pi, 0.01)


y2 = np.cos(x2) 
# 绘制折线图,指定每条曲线的采样点位置和线条属性

lines = plt.plot(x1, y1, 'r-', x2, y2, 'b-.') 
plt.legend(lines, ['sin','cos']) # 为两条曲线创建图例

plt.show() 

例3-6 绘制龟兔赛跑中兔子和乌龟的行走轨迹。运行结果如图3-9 所示。

图3-9 例3-6程序运行结果
import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.font_manager as fm 
视频二维码:例3-6 

t = np.arange(0, 120, 0.5) # 时间轴

rabbit = np.piecewise(t, # 兔子的运行轨迹,分段函数 
[t<10, t>110], # 兔子跑步的两个时间段 
[lambda x:15*x, # 兔子第一段时间的路程 
lambda x:20*(x-110)+150, # 第二个时间段的路程 
lambda x:150]) # 兔子中间睡觉时的路程

tortoise = 3 * t # 小乌龟一直在匀速前进

224 

PsxZW.indd 224 


2023/5/30 14:28:04 


225 
plt.plot(t, tortoise, label='乌龟', lw=3) 
plt.plot(t, rabbit, label='兔子') 
plt.title('龟兔赛跑', fontproperties='STKAITI', fontsize=24) 
plt.xlabel('时间(秒)', fontproperties='STKAITI', fontsize=18) 
plt.ylabel('与起点的距离(米)', fontproperties='simhei', fontsize=18) 
myfont = fm.FontProperties(fname=r'C:\Windows\Fonts\STKAITI.ttf', size=12) 
plt.legend(prop=myfont) # 设置图例中的中文字体和字号
plt.show() 
例3-7 一笔绘制红色五角星。运行结果如图3-10 所示。
代码一:
图3-10 例3-7 程序运行结果
import numpy as np 
import matplotlib.pyplot as plt 
r = 6 # 外接圆半径
angles = np.linspace(0, 2*np.pi, 5, endpoint=False) 
x = r * np.sin(angles) 
y = r * np.cos(angles) 
plt.plot([x[2],x[0],x[3],x[1],x[4],x[2]], 
[y[2],y[0],y[3],y[1],y[4],y[2]], 'r') 
plt.gca().set_aspect('equal') # 设置坐标轴纵横比相等
plt.show() 
代码二:
import numpy as np 
视频二维码:例3-7 
PsxZW.indd 225 2023/5/30 14:28:05 

226226import matplotlib.pyplot as plt 
r = 6 
angles = np.linspace(0, 4*np.pi, 6) 
x = r * np.sin(angles) 
y = r * np.cos(angles) 
plt.plot(x, y, 'r') 
plt.gca().set_aspect('equal') 
plt.show() 
例3-8 使用三角函数绘制花瓣图案。运行结果如图3-11 所示。
import numpy as np 
import matplotlib.pyplot as plt 
r = 6 
angles = np.arange(0, np.pi*2, 0.01) 
x = r * np.cos(4*angles) * np.cos(angles) # 把4 改成其他数字可以得到不同图案
y = r * np.cos(4*angles) * np.sin(angles) 
plt.plot(x, y, 'r') 
plt.gca().set_aspect('equal') 
plt.show() 
图3-11 例3-8 程序运行结果
例3-9 某质点的初始速度和加速度已知,绘制该质点第5~20s 速度和位移的曲线。
运行结果如图3-12 所示。
import numpy as np 
PsxZW.indd 226 2023/5/30 14:28:06 

import matplotlib.pyplot as plt 

v0, a = 3, 1.8 # 初始速度和加速度
t = np.arange(5, 21) # 时间轴,第5~20s 视频二维码:例3-9 
v = v0 + a*t # 速度
x = v0*t + 0.5*a*t*t # 位移
fig, (ax1, ax2) = plt.subplots(1, 2) # 创建左、右两个子图
# 设置子图之间的水平间距,wspace值为子图平均宽度的比例
plt.subplots_adjust(wspace=0.5) 
plt.sca(ax1) # 选择左边子图为当前子图
plt.plot(t, v, c='red') # 在当前子图中绘制折线图
plt.title('时间-速度', fontproperties='STKAITI', fontsize=24) 
plt.xlabel('时间(s)', fontproperties='STKAITI', fontsize=18) 
plt.ylabel('速度(m/s)', fontproperties='STKAITI', fontsize=18) 
plt.xlim(5, 21) # 设置坐标轴刻度范围
plt.ylim(0, 40) 


plt.sca(ax2) # 选择右边子图为当前子
图
plt.plot(t, x, c='blue') # 在当前子图中绘制折线
图
plt.title('时间-位移', fontproperties='STKAITI', fontsize=24)
plt.xlabel('时间(s)', fontproperties='STKAITI', fontsize=18)
plt.ylabel('位移(m)', fontproperties='STKAITI', fontsize=18)
plt.xlim(5, 21)
plt.ylim(0, 450)
plt.show(
)



图3-12 例3-9 程序运行结果

227 

PsxZW.indd 227 


2023/5/30 14:28:07 


例3-10 绘制误差线图。运行结果如图3-13 所示。

import numpy as np 
import matplotlib.pyplot as plt 


x, y = [1, 3, 5, 8, 9], [5, 9, 3, 5, 10] 视频二维码:例3-10 
plt.errorbar(x, y, # 数据点位置

 xerr=1, yerr=[1,1,1,0.5,0.5], # 两个方向的误差范围 
# 设置线条和端点符号 
# fmt='none'时表示不绘制数据点及连线,只绘制误差标记

 fmt='-.*', 
ecolor='orange', # 误差线颜色 
errorevery=2, # 每2 个数据点绘制一个误差线 
lolims=True, # 只绘制上侧的误差线 
xlolims=True) # 只绘制右侧的误差线

plt.show() 

图3-13 例3-10 程序运行结果
例3-11 已知某学校附近一个烧烤店2022 年每个月的营业额如
表3-3所示。编写程序绘制折线图对该烧烤店全年营业额进行可视化,
使用红色点画线连接每个月的数据,并在每个月的数据处使用三角形
进行标记。运行结果如图3-14 所示。视频二维码:例3-11 
表3-3 烧烤店营业额

月份
营业额/万元
1 

2 

3 

4 

5 

6 

7 

8 

9 

10 

11 

12 

5.2 

2.7 

5.8 

5.7 

7.3 

9.2 

18.7 

15.6 

20.5 

18.0 
7.8 
6.9 
228 

PsxZW.indd 228 


2023/5/30 14:28:09 


import matplotlib.pyplot as plt


month = range(1, 13)
money = [5.2, 2.7, 5.8, 5.7, 7.3, 9.2, 18.7, 15.6, 20.5, 18.0, 7.8, 6.9]
# 参数mfc(marker face color)设置散点符号内部颜
色
# 参数mec(marker edge color)设置散点符号边线颜
色
plt.plot(month, money, 'r-.v', mfc='b', mec='y'
)
plt.xlabel('月份', fontproperties='simhei', fontsize=14)
plt.ylabel('营业额(万元)', fontproperties='simhei', fontsize=14)
plt.title('烧烤店2022 年营业额变化趋势图', fontproperties='simhei'
,


 fontsize=18) 
plt.tight_layout() # 紧缩四周空白,扩大绘图区域可用面积
plt.show() 

图3-14 例3-11 程序运行结果
例3-12 绘制折线图模拟连续信号与数字信号。运行结果如图3-15 所示。
import numpy as np 
import matplotlib.pyplot as plt 
t = np.arange(0, 6*np.pi, 0.05) 视频二维码:例3-12
# 连续信号与数字信号的函数
值
t_sin = np.sin(t)
t_digital1 = np.piecewise(t_sin, [t_sin>0, t_sin<0], [1,-1]
)
t_digital2 = np.round_(t_sin)
# 在标签字符串首尾加$ 符号可以调用Latex 引擎渲染为公
式
plt.plot(t, t_sin, label='$sin(x)$', color='red', lw=1)


229 


2023/5/30 14:28:10

PsxZW.indd 229 


230230plt.plot(t, t_digital1, 'b--', label='digital1') 
plt.plot(t, t_digital2, 'g-.', label='digital2') 
plt.ylim(-2.0, 2.0) 
plt.legend() 
plt.show() 
图3-15 例3-12 程序运行结果
例3-13 绘制尼哥米德蚌线。
给定一条定直线m 和直线外一个定点O。定点与定直线的距离为a。过定点O 作一条
直线n 与定直线m 交于点P。在直线n上点P 的两侧分别取到点P 的距离为b 的点Q 和点
Q'。那么,点P在直线m上运动时,点Q和Q'的运动轨迹合在一起就叫作尼哥米德蚌线(或
尼科梅德斯蚌线)。图3-16 演示了尼哥米德蚌线的生成原理,分3 种可能的情况:①a>b 
时,蚌线的两支都不经过点O,如图3-17 左侧图形所示;②a=b 时,蚌线有一支有一个
尖点经过点O,如图3-17 中间图形所示;③a<b 时,蚌线有一支经过点O 且在O 处有一
个小绕环,如图3-17 右侧图形所示。
图3-16 尼哥米德蚌线生成原理
视频二维码:例3-13 
PsxZW.indd 230 2023/5/30 14:28:14 

图3-17 例3-13 程序运行结果

import numpy as np
import matplotlib.pyplot as plt


def draw(a, b)
: 
plt.figure(figsize=(10, 200), dpi=240) 
t = np.arange(-1.55, 1.55, 0.01) 
x1 = a + b*np.cos(t) 
y1 = a*np.tan(t) + b*np.sin(t) 
x2 = a - b*np.cos(t) 
y2 = a*np.tan(t) - b*np.sin(t) 
plt.plot(x1, y1, x2, y2) 
plt.title(f'{a=},{b=}'
) 
plt.ylim(-10, 10) 
plt.gca().set_aspect('equal'
) 
plt.savefig('{},{}.jpg'.format(a,b)
)


draw(3, 1)
draw(2, 2)
draw(0.3, 0.8)


例3-14 在第一象限中,任意反比例函数xy=k 与任意矩形OABC 
的两个交点的连线始终与矩形对角线平行,编写程序验证这一点。运
行结果如图3-18 所示。


视频二维码:例3-14 

231 


PsxZW.indd 231 


2023/5/30 14:28:16 


232232import numpy as np 
import matplotlib.pyplot as plt 
k = 1 # 反比例函数xy=k 的常数k 
m, n = 6, 3 # 矩形右上角坐标(m,n) 
x = np.arange(0.1, m+0.5, 0.02) # 第一象限中反比例函数曲线上顶点的x坐标
y = k / x # 根据反比例函数xy=k 计算顶点y 坐标
plt.plot(x, y, 'b') # 绘制第一象限指定区间内的反比例函数图像
# 绘制矩形,从左下角出发,向右、上、左、下
plt.plot([0,m,m,0,0], [0,0,n,n,0], 'r') 
plt.plot([0,m], [n,0], 'g') # 矩形对角线
plt.plot([k/n,m], [n,k/m], 'g') # 矩形与反比例函数的交点连线
for x, y, ch in zip([0,m,m,0,k/n,m], [0,0,n,n,n,k/m], 'OABCDE'): 
plt.text(x, y+0.02, ch) # 绘制顶点与交点的符号
plt.xlim(-0.1, m+1) # 设置坐标轴跨度
plt.ylim(-0.1, n+1) 
plt.title(f'k={k},m={m},n={n}', fontsize=20) # 设置图形标题
plt.gca().set_aspect(True) # 设置图形纵横比相等
plt.show() 
图3-18 例3-14 程序运行结果
例3-15 绘制函数曲线,计算并标记极值。运行结果如图3-19 所示。
代码一:
import numpy as np 
import matplotlib.pyplot as plt 
start, end = 0, 10 # 函数自变量取值范围
x = np.arange(start, end, 0.01) # 计算所有采样点的x坐标、y坐标
视频二维码:例3-15 
PsxZW.indd 232 2023/5/30 14:28:17 

233 
y = 3*np.sin(x) + 5*np.cos(3*x) 
s, = plt.plot(x, y, 'r-') # 绘制折线图,保存绘制结果
# 设置子区间长度,在每个子区间(不包含端点)内寻找极值
# 调整区间大小时会影响极值数量,应使得每个子区间内都包含波峰和波谷
span = 66 
for start in range(0, len(y), span): 
sectionY = y[start:start+span] # 每个子区间的自变量与函数值 
sectionX = x[start:start+span] 
localMax = sectionY.max() # 局部最大值和局部最小值 
localMin = sectionY.min() 
# 方案一: 
argsort_result = sectionY.argsort() # 按值大小升序排序的索引 
# 区间内所有最大值的索引和所有最小值的索引 
args_max = argsort_result[-len(sectionY[sectionY==localMax]):] 
args_min = argsort_result[:len(sectionY[sectionY==localMin])] 
args_max = list(set(args_max)-{0,span-1}) # 去除子区间端点 
if args_max: 
s1 = plt.scatter(sectionX[args_max], sectionY[args_max], 
marker='*', c='b') 
args_min = list(set(args_min)-{0,span-1}) 
if args_min: 
s2 = plt.scatter(sectionX[args_min], sectionY[args_min], 
marker='*', c='g') 
# 方案二:
## for index, yy in enumerate(sectionY): 
## if yy==localMax and index not in (0, span-1): 
## # 在极大值处绘制一个蓝色五角星
## s1 = plt.scatter(sectionX[index], yy, marker='*', c='b') 
## elif yy==localMin and index not in (0, span-1): 
## # 在极小值处绘制一个绿色五角星
## s2 = plt.scatter(sectionX[index], yy, marker='*', c='g') 
plt.legend([s,s1,s2], ['curve','local max','local min']) 
plt.show() 
代码二:
import numpy as np 
import matplotlib.pyplot as plt 
start, end = 0, 10 
x = np.arange(start, end, 0.01) 
PsxZW.indd 233 2023/5/30 14:28:17 

y = 3*np.sin(x) + 5*np.cos(3*x) 
s, = plt.plot(x, y, 'r-') 

for index, yy in enumerate(y): 
if index == 0: 
if yy > y[1]: 
s1 = plt.scatter(x[index], yy, marker='*', c='b') 
elif yy < y[1]: 
s2 = plt.scatter(x[index], yy, marker='*', c='g') 
elif index == len(y)-1: 
if yy > y[index-1]: 
s1 = plt.scatter(x[index], yy, marker='*', c='b') 
elif yy < y[index-1]: 
s2 = plt.scatter(x[index], yy, marker='*', c='g') 
elif yy>=y[index-1] and yy>=y[index+1]: 
s1 = plt.scatter(x[index], yy, marker='*', c='b') 
elif yy<=y[index-1] and yy<=y[index+1]: 
s2 = plt.scatter(x[index], yy, marker='*', c='g') 

plt.legend([s,s1,s2], ['curve','local max','local min']) 
plt.show() 


图3-19 例3-15 程序运行结果

例3-16 使用折线图可视化角谷猜想(给定任意正整数,如果
是
偶数就除以2,如果是奇数就乘以3 再加1,最终总能得到1)中正
整
数变为1 的过程。运行结果如图3-20 所示
。



视频二维码:例3-16 

234 

PsxZW.indd 234 


2023/5/30 14:28:18