动图
很多时候我们绘图不仅仅是绘制最终的统计结果图,而是想看看在不同参数不同时刻下的连续图形,这个在仿真模拟的时候相当有用。比如机器学习中,参数的变化导致的变化,比如我最近做的库存水平变化模拟等。如果我们绘制静态图像,只能看到某一时刻的直观图形,如果加入时间线,那么就能直观感受变量的变化过程。
其实原理也挺简单的,就是创建一幅图,定义图形中曲线,散点,标注等各个对象,然后在不同时刻,更新这些对象的数据,matplotlib会自动根据新的数据刷新图形。
动图的核心函数是
matplotlib.animation.FuncAnimation
,基本用法是:
anim = animation.funcanimation(fig, animate, init_func=init, frames=100, interval=20, blit=true)
下面通过几个例子来说明使用方法。
例子1
第一个例子参考:
http://codingpy.com/article/drawing-gifs-with-matplotlib/?utm_source=tuicool&utm_medium=referral
该文绘制不同参数状态下的图形,很有意思,这里简化一些代码,顺便增加更多注释。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import seaborn as sns
sns.set_style("whitegrid")
fig, ax = plt.subplots()
fig.set_tight_layout(True)
x = np.arange(0, 20, 0.1)
ax.scatter(x, x + np.random.normal(0, 3.0, len(x)))
line, = ax.plot(x, x - 5, 'r-', linewidth=2)
def update(i):
label = 'timestep {0}'.format(i)
print(label)
line.set_ydata(x - 5 + i)
ax.set_xlabel(label)
return line, ax
anim = FuncAnimation(fig, update, frames=np.arange(0, 10), interval=200)
例子2
为了代码更加通用,我们绘制上下两个子图,每个子图绘制正弦波和散点图的组合。
重点是散点图的绘制,线图和例子1一样,都是更新x,y轴数据即可。
散点图用
set_offsets(data)
函数,而且
data
的数据格式是
[[x1,y1],[x2,y2]...]
,而不像直线,其数据格式是x轴的放在一起,y轴的放在一起。
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
import seaborn as sns
sns.set_style("whitegrid")
def randn_point():
x=np.random.randint(1,100,3)
y=np.random.randint(1,2,3)
return x,y
fig = plt.figure(figsize=(15, 10))
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2)
x = np.arange(0, 2*np.pi, 0.01)
line1, = ax1.plot(x, np.sin(x))
x1,y1=randn_point()
sca1 = ax1.scatter(x1,y1)
line2, = ax2.plot(x, np.cos(x))
x2,y2=randn_point()
sca2 = ax2.scatter(x2,y2)
def init():
line1.set_ydata(np.sin(x))
line1.set_ydata(np.cos(x))
x1, y1 = randn_point()
x2, y2 = randn_point()
data1 = [[x,y] for x,y in zip(x1,y1)]
data2 = [[x, y] for x, y in zip(x2, y2)]
sca1.set_offsets(data1)
sca2.set_offsets(data2)
label = 'timestep {0}'.format(0)
ax1.set_xlabel(label)
return line1,line2,sca1,sca2,ax1
def animate(i):
line1.set_ydata(np.sin(x + i/10.0))
line2.set_ydata(np.cos(x + i / 10.0))
x1, y1 = randn_point()
x2, y2 = randn_point()
data1 = [[x,y] for x,y in zip(x1,y1)]
data2 = [[x, y] for x, y in zip(x2, y2)]
sca1.set_offsets(data1)
sca2.set_offsets(data2)
label = 'timestep {0}'.format(i)
ax1.set_xlabel(label)
return line1,line2,sca1,sca2,ax1
ani = animation.FuncAnimation(fig=fig,
func=animate,
frames=100,
init_func=init,
interval=20,
blit=False)
plt.show()
保存图形
保存图形要用到一个叫
ImageMagick
的工具,按照网上的参考文章,都是使用
ImageMagick 6.9
版本,第一次下载最新版,怎么都没找到convert模块,好坑啊。
步骤:
1。下载安装
ImageMagick 6.9
,安装过程中选择默认选项即可。
2。找到
"python_homeLibsite-packagesmatplotlibmpl-datamatplotlibrc"
,
修改convert路径
#animation.convert_path: 'convert'
–>
#animation.convert_path: 'C:Program Files (x86)ImageMagick-6.9.2-Q16convert.exe'
在绘图后增加一个save操作:
ani = animation.FuncAnimation(fig=fig,
func=animate,
frames=100,
init_func=init,
interval=20,
blit=False)
plt.show()
ani.save(r'D:demoanimation.gif', writer='imagemagick', fps=2)
参考
使用Matplotlib制作动图
http://blog.csdn.net/theonegis/article/details/51037850
如何用 Matplotlib 画 GIF 动图
https://www.tuicool.com/articles/Z7BzY3V
使用Matplotlib和Imagemagick实现算法可视化与GIF导出
http://www.hankcs.com/ml/using-matplotlib-and-imagemagick-to-realize-the-algorithm-visualization-and-gif-export.html
利用Matplotlib和ImageMagick制作gif动画
http://blog.csdn.net/stereohomology/article/details/35845399
matplotlib里的动画
http://blog.csdn.net/riverflowrand/article/details/51189573
官方动画教程
http://matplotlib.org/api/animation_api.html