博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
『科学计算』科学绘图库matplotlib学习之绘制动画
阅读量:5346 次
发布时间:2019-06-15

本文共 11370 字,大约阅读时间需要 37 分钟。

基础

1.matplotlib绘图函数接收两个等长list,第一个作为集合x坐标,第二个作为集合y坐标

2.基本函数:

animation.FuncAnimation(fig, update_point,data)

  • fig是画布
  • update是绘画函数需自己定义,需要一个参数,会自动接收data,需要返回plt.plot对象,描述比较费解,看例子就好
  • data种类很多,包括总帧数(例1)、当前帧数(即不设定data的默认参数,例2)、返回迭代器的函数(例3)、list(作业2)
  • frames=200 总帧数(非update参数)
  • interval=20  帧间隔(毫秒)

示例代码

简单调用帧数绘图

from matplotlib import pyplot as pltimport matplotlib.animation as animationimport numpy as npdef update_point(num):    fig_points.set_data(data[:, 0:num])    return fig_points,fig1 = plt.figure()num_point = 50data = np.random.rand(2, num_point)fig_points, = plt.plot([], [], 'ro')plt.xlim(0, 1)plt.ylim(0, 1)plt.xlabel('x')plt.title('Scatter Point')# interval# repeat# frames# fargs# init_funcanim = animation.FuncAnimation(fig1, update_point,num_point)#anim = animation.FuncAnimation(fig1, update_point,frames=num_point, interval=50, blit=False, repeat=False)plt.show()

 

 

利用帧做参数绘制

这种方式每经过interval的时间后会调用函数(传入当前帧号)绘制一幅新图更新原图:

  1. 建立子图、空白线
  2. 创建动画发生时调用的函数

    Init()是我们的动画在在创建动画基础框架(base frame)时调用的函数。这里我们们用一个非常简单的对line什么都不做的函数。这个函数一定要返回line对

    象,这个很重要,因为这样就能告诉动画之后要更新的内容,也就是动作的内容是line。--来自( )

  3. 动画函数

    在这个动画函数中修改你的图

  4. 调用函数生成动态图

 

绘制正弦波函数:

可以使用多个线对象来同时更新多个子图于同一个动画生成器之中,不过这需要上面1~3步同时支持(就是写出来)多个线对象

import numpy as npfrom matplotlib import pyplot as pltfrom matplotlib import animation# 1.First set up the figure, the axis, and the plot element we want to animatefig = plt.figure()ax = plt.axes(xlim=(0,2),ylim=(-2,2))line, = ax.plot([],[],lw=2)# 2.initialization function: plot the background of each framedef init():    line.set_data([],[])    return line,# 3.animation function.  This is called sequentially# note: i is framenumberdef update(i):    x = np.linspace(0,2,1000)    y = np.sin(2 * np.pi * (x - 0.01 * i))  # 调整x相当于向右平移图像    line.set_data(x,y)    return line,# call the animator.  blit=True means only re-draw the parts that have changed.# 画布, 使用帧数做参数的绘制函数, init生成器.。anim = animation.FuncAnimation(fig,update,init_func=init,frames=200,interval=20,blit=False)# frames=200   帧数# interval=20  间隔# anim.save('anim3.mp4', fps=30, extra_args=['-vcodec', 'libx264'])      # 保存为mp4# anim.save('anim3.gif', writer='imagemagick')                           # 保存为gifplt.show()

 

迭代器绘制法

绘制衰减波

这里的update函数仅仅绘制图像,数据生成被移植到函数data_gen中了,而上面的帧方法中update得到帧号后会自己生成数据。

 

import numpy as npimport matplotlib.pyplot as pltimport matplotlib.animation as animationdef data_gen():    t = 0    cnt = 0    while cnt < 200:        cnt += 1        t += 0.1        yield t,np.sin(2 * np.pi * t) * np.exp(-t / 10.)def init():    ax.set_ylim(-1.1,1.1)    ax.set_xlim(0,10)    line.set_data([],[])    return line,def update(datag):    # update the data,默认接受后面的yield    t,y = datag    xdata.append(t)    ydata.append(y)    line.set_data(xdata,ydata)    if max(xdata) > 10:        ax.set_xlim(max(xdata) - 10,max(xdata))    return line,fig,ax = plt.subplots()line, = ax.plot([],[],lw=2)ax.grid()xdata,ydata = [],[]# 参数:{画布,绘制图像函数,更新数据函数,时间间隔,重复标识,初始化函数}ani = animation.FuncAnimation(fig,update,data_gen,interval=10,repeat=False,init_func=init)plt.show()

作业

冒泡排序算法动画演示

使用迭代器更新方式:

参考:

import numpy as np  import matplotlib.pyplot as plt  import matplotlib.animation as animation    fig = plt.figure()  axes1 = fig.add_subplot(111)  line, = axes1.plot(np.random.rand(10))    #因为update的参数是调用函数data_gen,所以第一个默认参数不能是framenum  def update(data):      line.set_ydata(data)      return line,  # 每次生成10个随机数据  def data_gen():      while True:          yield np.random.rand(10)    ani = animation.FuncAnimation(fig, update, data_gen, interval=2*1000)  plt.show()

代码:

import numpy as npfrom matplotlib import pyplot as pltfrom matplotlib import animationfig = plt.figure()ax = fig.add_subplot(111)line, = ax.plot(np.zeros(9),'bo')  # 由于没有使用init_fun,所以初始帧有数据,且尺寸与后续帧一致才行ax.set_xlim(0,10)ax.set_ylim(0,10)ax.set_xticks(np.linspace(0,10,11))ax.set_yticks(np.linspace(0,10,11))ax.grid(True)# update的参数是调用函数data_gendef update(data):    line.set_xdata(np.linspace(1,9,9))    line.set_ydata(data)    return line,def data_gen():    x = [9,8,3,1,2,4,6,5,7]    for i in range(len(x)-1):        for j in range(len(x)-1):            if x[j]>x[j+1]:                x[j],x[j+1]=x[j+1],x[j]            yield(x)# {画布,绘制函数(数据函数yield),数据函数,帧间隔(毫秒),重复标识}ani = animation.FuncAnimation(fig,update,data_gen,interval=1000,repeat=False)plt.show()

 

快速排序算法动画演示

使用数组更新方式:

  • 不把数据以迭代器的方式传入,而是list,则每次会把list的子项依次传入update。list形式是[ [list1], [list2], ... ... ]。
  • 另外使用了init_fun,使用这个函数了后不用绘制初始帧,即可以使用:line = ax.plot([],[],'go'),而不用指定初始化数据,但是这样的话x轴数据update需要设定好才行(因为默认继承初始帧的x轴)。

 

参考:

例子使用list(metric),每次会从metric中取一行数据作为参数送入update中

import numpy as np      import matplotlib.pyplot as plt      import matplotlib.animation as animation            start = [1, 0.18, 0.63, 0.29, 0.03, 0.24, 0.86, 0.07, 0.58, 0]            metric =[[0.03, 0.86, 0.65, 0.34, 0.34, 0.02, 0.22, 0.74, 0.66, 0.65],               [0.43, 0.18, 0.63, 0.29, 0.03, 0.24, 0.86, 0.07, 0.58, 0.55],               [0.66, 0.75, 0.01, 0.94, 0.72, 0.77, 0.20, 0.66, 0.81, 0.52]              ]            fig = plt.figure()      window = fig.add_subplot(111)      line, = window.plot(start)      #如果是参数是list,则默认每次取list中的一个元素,即metric[0],metric[1],...      def update(data):          line.set_ydata(data)          return line,            ani = animation.FuncAnimation(fig, update, metric, interval=2*1000)      plt.show()

代码:

import numpy as npfrom matplotlib import pyplot as pltfrom matplotlib import animationimport copyobj = [49,38,65,97,76,13,27,49]res = []def fast_sort(ob,start,end):    # print(ob,start,end)    if  end - start <= 1:        return    # i,j,k = 0,(len(ob)-1),ob[0]    i,j,k = start,end,ob[start]    while j-i != 1:        for j_r in range(j,i,-1):            j = j_r            if ob[j_r]
k: ob[i_r],ob[j] = ob[j],ob[i_r] break res.append(copy.deepcopy(ob)) # 这里发现添加进res的list对象是浅拷贝,或者说向数据结构中添加的list都是浅拷贝,需要注意 if ob[i] == k: fast_sort(ob,start,i-1) fast_sort(ob,i+1,end) else: fast_sort(ob,start,j-1) fast_sort(ob,j+1,end)fast_sort(obj,0,(len(obj)-1))print(res)fig = plt.figure()ax = fig.add_subplot(111)ax.set_xlim(0,8)ax.set_ylim(0,100)ax.set_xticks(np.linspace(0,8,9))ax.set_yticks(np.linspace(0,100,11))ax.grid()line, = ax.plot([],[],'go')def init(): line.set_data([], []) return line,def update(data): # update函数参数默认接收其后的函数或是list line.set_xdata(np.linspace(0,7,8)) line.set_ydata(data) return lineani = animation.FuncAnimation(fig,update,res,init_func=init,interval=2*1000,repeat=False)

 冒泡排序&快速排序代码

两种排序具体定义自行百度,不过比较重要的一点是快速排序属于递归过程,蛮好玩的。

冒泡排序

import numpy as npob = [9,8,3,1,2,4,6,5,7]def oppo_sort(x):    for i in range(len(x)-1):        for j in range(len(x)-1):            if x[j]>x[j+1]:                x[j],x[j+1]=x[j+1],x[j]            yield((i,j),x)for t,obj in oppo_sort(ob):    print(t,obj)
(0, 0) [8, 9, 3, 1, 2, 4, 6, 5, 7](0, 1) [8, 3, 9, 1, 2, 4, 6, 5, 7](0, 2) [8, 3, 1, 9, 2, 4, 6, 5, 7](0, 3) [8, 3, 1, 2, 9, 4, 6, 5, 7](0, 4) [8, 3, 1, 2, 4, 9, 6, 5, 7](0, 5) [8, 3, 1, 2, 4, 6, 9, 5, 7](0, 6) [8, 3, 1, 2, 4, 6, 5, 9, 7](0, 7) [8, 3, 1, 2, 4, 6, 5, 7, 9](1, 0) [3, 8, 1, 2, 4, 6, 5, 7, 9](1, 1) [3, 1, 8, 2, 4, 6, 5, 7, 9](1, 2) [3, 1, 2, 8, 4, 6, 5, 7, 9](1, 3) [3, 1, 2, 4, 8, 6, 5, 7, 9](1, 4) [3, 1, 2, 4, 6, 8, 5, 7, 9](1, 5) [3, 1, 2, 4, 6, 5, 8, 7, 9](1, 6) [3, 1, 2, 4, 6, 5, 7, 8, 9](1, 7) [3, 1, 2, 4, 6, 5, 7, 8, 9](2, 0) [1, 3, 2, 4, 6, 5, 7, 8, 9](2, 1) [1, 2, 3, 4, 6, 5, 7, 8, 9](2, 2) [1, 2, 3, 4, 6, 5, 7, 8, 9](2, 3) [1, 2, 3, 4, 6, 5, 7, 8, 9](2, 4) [1, 2, 3, 4, 5, 6, 7, 8, 9](2, 5) [1, 2, 3, 4, 5, 6, 7, 8, 9](2, 6) [1, 2, 3, 4, 5, 6, 7, 8, 9](2, 7) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 0) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 1) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 2) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 3) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 4) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 5) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 6) [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 7) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 0) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 1) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 2) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 3) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 4) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 5) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 6) [1, 2, 3, 4, 5, 6, 7, 8, 9](4, 7) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 0) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 1) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 2) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 3) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 4) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 5) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 6) [1, 2, 3, 4, 5, 6, 7, 8, 9](5, 7) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 0) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 1) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 2) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 3) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 4) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 5) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 6) [1, 2, 3, 4, 5, 6, 7, 8, 9](6, 7) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 0) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 1) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 2) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 3) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 4) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 5) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 6) [1, 2, 3, 4, 5, 6, 7, 8, 9](7, 7) [1, 2, 3, 4, 5, 6, 7, 8, 9]

快速排序

有坑,不仅是因为快速排序本身比较复杂的原因,由于python的拷贝机制,实现起来也有一些注意的地方,注意在探究python拷贝机制的时候id()是个有用的函数。

 

本段方法出错了,原因试python在给函数传入list的时候按照是浅拷贝的(即对同一id操作),但是,一旦传入的是切片,那么就会分配id进行深拷贝,其实不难理解,毕竟对于一个函数可以看作一个较为独立的节点,其中的元素都要有自己完整的标识,即自己的id:

obj = [49,38,65,97,76,13,27,49]def fast_sort(ob):    # print(id(ob))    if len(ob) <= 1:        return    i,j,k = 0,(len(ob)-1),ob[0]    while j-i != 1:        for j_r in range(j,i,-1):            j = j_r            if ob[j_r]
k: ob[i_r],ob[j] = ob[j],ob[i_r] break print(ob) if ob[i] == k: fast_sort(ob[:i]) fast_sort(ob[i+1:]) else: fast_sort(ob[:j]) fast_sort(ob[j+1:])fast_sort(obj)
[27, 38, 49, 97, 76, 13, 65, 49][27, 38, 13, 49, 76, 97, 65, 49][27, 38, 13, 49, 76, 97, 65, 49][13, 27, 38][49, 76, 65, 97][49, 65, 76, 97]

可以清晰地验明上述结论:

ls = [1,2,3,4,5]i = 0def print_id(l1,l2):    global i    i += 1    if i == 10:return    print(id(l1),'  ',id(l2))    print_id(l1,l2[1:2])print_id(ls,ls)
2424669584200    24246695842002424669584200    24246696841682424669584200    24246696160082424669584200    24246696158802424669584200    24246696149842424669584200    24246695480402424669584200    24246696147922424669584200    24246695847122424669584200    2424669497992

python凡是涉及到修改数据结构都应该遵循如下方式:传入原始数据结构,传入索引,在函数内部使用索引修改数据结构而不是直接传入数据结构的一部分,下面是正确的写法。

顺便注意一下递归函数的写法:终止判断+主函数体+递归调用分部

import copyobj = [49,38,65,97,76,13,27,49]res=[]def fast_sort(ob,start,end):    # print(ob,start,end)    if  end - start <= 1:        return    # i,j,k = 0,(len(ob)-1),ob[0]    i,j,k = start,end,ob[start]    while j-i != 1:        for j_r in range(j,i,-1):            j = j_r            if ob[j_r]
k: ob[i_r],ob[j] = ob[j],ob[i_r] break print(ob) res.append(copy.deepcopy(ob)) # 注意深拷贝 print(res) if ob[i] == k: fast_sort(ob,start,i-1) fast_sort(ob,i+1,end) else: fast_sort(ob,start,j-1) fast_sort(ob,j+1,end) fast_sort(obj,0,(len(obj)-1))print(obj)
[27, 38, 13, 49, 76, 97, 65, 49][[27, 38, 13, 49, 76, 97, 65, 49]][13, 27, 38, 49, 76, 97, 65, 49][[27, 38, 13, 49, 76, 97, 65, 49], [13, 27, 38, 49, 76, 97, 65, 49]][13, 27, 38, 49, 49, 65, 76, 97][[27, 38, 13, 49, 76, 97, 65, 49], [13, 27, 38, 49, 76, 97, 65, 49], [13, 27, 38, 49, 49, 65, 76, 97]][13, 27, 38, 49, 49, 65, 76, 97]

 

 

 

转载于:https://www.cnblogs.com/hellcat/p/7086850.html

你可能感兴趣的文章
Python环境搭建(安装、验证与卸载)
查看>>
一个.NET通用JSON解析/构建类的实现(c#)
查看>>
详谈js面向对象 javascript oop,持续更新
查看>>
关于这次软件以及pda终端的培训
查看>>
如何辨别一个程序员的水平高低?是靠发量吗?
查看>>
新手村之循环!循环!循环!
查看>>
线程安全问题
查看>>
linux的子进程调用exec( )系列函数
查看>>
MySQLdb & pymsql
查看>>
zju 2744 回文字符 hdu 1544
查看>>
【luogu P2298 Mzc和男家丁的游戏】 题解
查看>>
前端笔记-bom
查看>>
上海淮海中路上苹果旗舰店门口欲砸一台IMAC电脑维权
查看>>
Google透露Android Market恶意程序扫描服务
查看>>
给mysql数据库字段值拼接前缀或后缀。 concat()函数
查看>>
迷宫问题
查看>>
【FZSZ2017暑假提高组Day9】猜数游戏(number)
查看>>
泛型子类_属性类型_重写方法类型
查看>>
对闭包的理解
查看>>
练习10-1 使用递归函数计算1到n之和(10 分
查看>>