python动态图表变化_用 Matplotlib 库生成动画图表

bVbrSZX?w=504&h=504

更多文章请关注微信公众号:硬核智能

动画是一种展示现象的有趣方式。相对于静态图表,人类总是容易被动画和交互式图表所吸引。在描述多年来的股票价格、过去十年的气候变化、季节性和趋势等时间序列数据时,动画更有意义,因为我们可以看到特定的参数是怎样随时间变化的。

上面的图是雨滴的模拟并且已经使用 Matplotlib 库实现,该库是一个广为人知的祖父级别的 python 可视化包。 Matplotlib 通过对 50 个散点的比例和透明度进行设置来模拟雨滴。今天,Python 拥有大量强大的可视化工具,如 Plotly、Bokeh、Altair等等。这些库能够实现最先进的动画和交互特性。尽管如此,本文的目的是强调这个库的另一个方面,这个方面没有人进行过太多的探索,这就是动画。

概述

Matplotlib 是一个广受欢迎的 Python 2D 绘图库。很多人都是从 Matplotlib 开始数据可视化之旅的。可以使用matplotlib轻松生成图表、直方图、功率谱,条形图,错误图表,散点图等。它还与 Pandas 和 Seaborn 等库无缝集成,创造出更加复杂的可视化效果。

matplotlib 的优点是:

它的设计类似于 MATLAB,因此很容易在在两者之间切换。

在后端进行渲染。

可以重现任何图表(需要一点努力)。

已经存在了十多年,拥有庞大的用户群。

然而,也有一些方面 Matplotlib 落后于同类的库。

Matplotlib 有一个过于冗长的规则 API。

有时候风格很差。

对 Web 和交互式图表的支持不佳。

对于大型复杂数据而言通常很慢。

这份复习资料是来自

bVbrS0l?w=876&h=619

动画

Matplotlib 的 animation 基类负责处理动画部分。它提供了一个构建动画功能的框架。使用下面两个接口来实现:

FuncAnimation 通过重复调用函数 func 来产生动画。

ArtistAnimation: 动画使用一组固定的 Artist 对象。

但是,在这两个接口中,FuncAnimation 是最方便使用的。你可以通过阅读文档 得到的更多信息,因为我们只关注 FuncAnimation 工具。

要求

安装 numpy 和 matplotlib 。

要将动画保存为 mp4 或 gif,需要安装 ffmpeg 或 imagemagick。

准备好之后,我们就可以在 Jupyter note 中开始创建第一个动画了。可以从 Github 得到本文的代码。

基本动画:移动的正弦波

我们先用 FuncAnimation 创建一个在屏幕上移动的正弦波的动画。动画的源代码来自 Matplotlib 动画教程。首先看一下输出,然后我们会分析代码以了解幕后的原理。

import numpy as np

from matplotlib import pyplot as plt

from matplotlib.animation import FuncAnimation

plt.style.use('seaborn-pastel')

fig = plt.figure()

ax = plt.axes(xlim=(0, 4), ylim=(-2, 2))

line, = ax.plot([], [], lw=3)

def init():

line.set_data([], [])

return line,

def animate(i):

x = np.linspace(0, 4, 1000)

y = np.sin(2 * np.pi * (x - 0.01 * i))

line.set_data(x, y)

return line,

anim = FuncAnimation(fig, animate, init_func=init,

frames=200, interval=20, blit=True)

anim.save('sine_wave.gif', writer='imagemagick')

bVbrS03?w=640&h=480

在第(7-9)行中,我们只需在图中创建一个带有单个轴的图形窗口。然后创建一个空的行对象,它实际上是动画中要修改的对象。稍后将用数据对行对象进行填充。

在第(11-13)行中,我们创建了 init 函数,它将使动画开始。 init 函数对数据进行初始化并设置轴限制。

在第(14-18)行中,我们最终定义了动画函数,该函数将帧编号( i )作为参数并创建正弦波(或任何其他动画),这取决于 i 的值。此函数返回一个已修改的绘图对象的元组,它告诉动画框架哪些部分应该属于动画。

在第 20 行中,我们创建了实际的动画对象。 blit 参数确保只重绘那些已经改变的图块。

这是在 Matplotlib 中创建动画的基本方法。通过对代码进行一些调整,可以创建有趣的可视化图表。接下来看看更多的可视化案例。

一个不断增长的线圈

同样,在 GeeksforGeeks 中有一个很好的例子。现在让我们在 matplotlib 的 animation 类的帮助下创建一个缓慢展开的动圈。该代码非常类似于正弦波图,只需稍作调整即可。

import matplotlib.pyplot as plt

import matplotlib.animation as animation

import numpy as np

plt.style.use('dark_background')

fig = plt.figure()

ax = plt.axes(xlim=(-50, 50), ylim=(-50, 50))

line, = ax.plot([], [], lw=2)

# initialization function

def init():

# creating an empty plot/frame

line.set_data([], [])

return line,

# lists to store x and y axis points

xdata, ydata = [], []

# animation function

def animate(i):

# t is a parameter

t = 0.1*i

# x, y values to be plotted

x = t*np.sin(t)

y = t*np.cos(t)

# appending new points to x, y axes points list

xdata.append(x)

ydata.append(y)

line.set_data(xdata, ydata)

return line,

# setting a title for the plot

plt.title('Creating a growing coil with matplotlib!')

# hiding the axis details

plt.axis('off')

# call the animator

anim = animation.FuncAnimation(fig, animate, init_func=init,

frames=500, interval=20, blit=True)

# save the animation as mp4 video file

anim.save('coil.gif',writer='imagemagick')

bVbrS0M?w=432&h=288

实时更新图表

在绘制动态数量(如库存数据,传感器数据或任何其他时间相关数据)时,实时更新的图表会派上用场。我们绘制了一个简单的图表,当有更多数据被输入系统时,该图表会自动更新。下面让我们绘制一家假想公司在一个月内的股票价格。

# importing libraries

import matplotlib.pyplot as plt

import matplotlib.animation as animation

fig = plt.figure()

# creating a subplot

ax1 = fig.add_subplot(1,1,1)

def animate(i):

data = open('stock.txt','r').read()

lines = data.split('\n')

xs = []

ys = []

for line in lines:

x, y = line.split(',') # Delimiter is comma

xs.append(float(x))

ys.append(float(y))

ax1.clear()

ax1.plot(xs, ys)

plt.xlabel('Date')

plt.ylabel('Price')

plt.title('Live graph with matplotlib')

ani = animation.FuncAnimation(fig, animate, interval=1000)

plt.show()

现在,打开终端并运行 python 脚本。你将得到如下图所示的图表,该图表会自动更新:

bVbrS1x?w=876&h=545

这里的间隔是 1000 毫秒或一秒。

3D 图动画

创建 3D 图形是很常见的,但如果我们想要为这些图形的视角设置动画,该怎么办呢?我们的想法是更改摄像机视图,然后用每个生成的图像来创建动画。在 Python Graph Gallery 上有一个很好的例子。

在与 jupyter notebook 相同的目录中创建名为 volcano 的文件夹。所有图片文件都将存储在这里,然后将在动画中使用。

# library

from mpl_toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

import pandas as pd

import seaborn as sns

# Get the data (csv file is hosted on the web)

url = 'https://python-graph-gallery.com/wp-content/uploads/volcano.csv'

data = pd.read_csv(url)

# Transform it to a long format

df=data.unstack().reset_index()

df.columns=["X","Y","Z"]

# And transform the old column name in something numeric

df['X']=pd.Categorical(df['X'])

df['X']=df['X'].cat.codes

# We are going to do 20 plots, for 20 different angles

for angle in range(70,210,2):

# Make the plot

fig = plt.figure()

ax = fig.gca(projection='3d')

ax.plot_trisurf(df['Y'], df['X'], df['Z'], cmap=plt.cm.viridis, linewidth=0.2)

ax.view_init(30,angle)

filename='Volcano/Volcano_step'+str(angle)+'.png'

plt.savefig(filename, dpi=96)

plt.gca()

这将会在 Volcano 文件夹中创建多个 PNG 文件。现在用 ImageMagick 将它们转换为动画。打开终端并切换到 Volcano 目录下输入以下命令:

convert -delay 10 Volcano*.png animated_volcano.gif

bVbrS1I?w=576&h=384

使用 Celluloid 模块创建的动画

Celluloid 是一个Python模块,它简化了在 matplotlib 中创建动画的过程。这个库创建一个 matplotlib 图,并从中再创建一个 Camera。然后重新处理数据,并在创建每个帧后,用 camera 拍摄快照。最后创建包含所有帧的动画。

安装

pip install celluloid

以下是使用 Celluloid 模块的一些示例。

Minimal

from matplotlib import pyplot as plt

from celluloid import Camera

fig = plt.figure()

camera = Camera(fig)

for i in range(10):

plt.plot([i] * 10)

camera.snap()

animation = camera.animate()

animation.save('celluloid_minimal.gif', writer = 'imagemagick')

bVbrS1W?w=432&h=288

Subplot

import numpy as np

from matplotlib import pyplot as plt

from celluloid import Camera

fig, axes = plt.subplots(2)

camera = Camera(fig)

t = np.linspace(0, 2 * np.pi, 128, endpoint=False)

for i in t:

axes[0].plot(t, np.sin(t + i), color='blue')

axes[1].plot(t, np.sin(t - i), color='blue')

camera.snap()

animation = camera.animate()

animation.save('celluloid_subplots.gif', writer = 'imagemagick')

bVbrS2p?w=432&h=288

Legend

import matplotlib

from matplotlib import pyplot as plt

from celluloid import Camera

fig = plt.figure()

camera = Camera(fig)

for i in range(20):

t = plt.plot(range(i, i + 5))

plt.legend(t, [f'line {i}'])

camera.snap()

animation = camera.animate()

animation.save('celluloid_legends.gif', writer = 'imagemagick')

bVbrS27?w=432&h=288

总结

动画有助于突出显示无法通过静态图表轻松传达的某些功能。尽管如此,不必要的过度使用有时会使事情复杂化,应该明智地使用数据可视化中的每个功能以产生最佳效果。

更多文章请关注微信公众号:硬核智能

bVbrS4y?w=258&h=258

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值