可视化是数据描述的图形表示,旨在一目了然地揭示数据中的复杂信息。数据可视化在讲故事中的重要性不言而喻。
在可视化当中,我们常用的方式有点、线、面,或者说这几者组合。部分绘图结果可见下面链接: Python 画点线图、Python 画柱状图、Python 画柱状图(总结)
在可视化中最为复杂的要数动态图的绘制,动态图能表达出更多的信息(如时间维),包含二维(x,time)、三维(x,y,time)、四维(x,y,z,time)数据中的信息。
同时,动画可以有趣地展示某种现象。相比于静态图表,人们更容易被动画和交互式的图表所吸引。
由于博主本身专业的限制,只重点关注了地学的相关文献、代码,其他专业也可借鉴本文中的相关动态图制作方法。
动图可视化作品举例
在日常学习生活中,可以发现有非常多精彩的动态图可视化作品,这些动态图为工作的展现、数据的说明都起到锦上添花的效果。见下:
Example1:
该图基于MITgcm模式输出数据绘制
Example2:
该动图的左边反映的是缺氧区域随时间的变化,右边反映的是空间的变化
Example3:
新冠肺炎初期死亡人数的变化 该项目链接:GitHub bar_chart_race
这种动图也可用pandas_alive绘制,见下
Example4:
This animation shows the transport of air parcels continuously emitted from four point sources inside the canopy during a period of 2.5 hours for the simulation 该动图来源于SCI论文《地形对茂密森林内排放的气体在冠层内运输的影响》 Effects of topography on in-canopy transport of gases emitted within dense forests
接下来重点介绍GIF图的生成,需要注意的是,GIF的生成一般是需要安装imagemagick(图片处理工具),用pillow也行(但相对较有瑕疵)。
举例说明:基于matplotlib中的anamation
Test1:移动的sin曲线(通过更新数据方式)
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=100, interval=20, blit=True)
anim.save('sine_wave_pillow.gif', writer='pillow')
(备注: 这里保存GIF参数选用pillow,坐标轴显示不清晰,可选用imagemagick)
Test2:示波器上的李萨如图形(通过更新数据方式)
李萨如图形见下:
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)
def init():
line.set_data([], [])
return line,
xdata, ydata = [], []
def ghostImage(x,y):
xdata.append(x)
ydata.append(y)
if len(xdata)>60:
del xdata[0]
del ydata[0]
return xdata,ydata
def animate(i):
t = i/100.0
x = 40*np.sin(2*2*np.pi*(t+0.3))
y = 40*np.cos(3*2*np.pi*t)
line.set_data(ghostImage(x,y))
return line,
plt.title('Creating a Lissajous figure with matplotlib')
plt.axis('off')
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=400, interval=20, blit=True)
anim.save('figure.gif',writer='pillow')
Test3:二维动画绘制(通过叠加图像形式)
预先计算的【图像列表】的动画图像
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
ims = []
for i in range(60):
x += np.pi / 15.
y += np.pi / 20.
im = plt.imshow(f(x, y), animated=True)
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
repeat_delay=1000)
ani.save('test_2d.gif', writer='pillow')
Test4:二维动画绘制(通过替换数据的形式)
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
x = np.linspace(-10*np.pi,10*np.pi,300)
y = np.linspace(-10*np.pi,10*np.pi,300)
X,Y = np.meshgrid(x,y)
img = plt.imshow(np.sin(X),cmap='ocean')
nums = 1000
def init():
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
return img
def update(step):
z = np.cos((0.5*X*(np.cos(0.01*step)+0.1))+step)+np.sin(0.5*(Y*(np.sin(0.01*step)+0.1))+step)
img.set_data(z)
return img
ani = FuncAnimation(fig, update, frames=nums,
init_func=init,interval=100)
ani.save('example4.gif', writer='pillow')
备注:以上皆是利用matplotlib中的anamation绘制,还可以利用上文提到的pandas_alive进行绘制
举例说明:基于pandas_alive
Test5:x轴显示固定
import pandas as pd
import pandas_alive
elec_df = pd.read_csv("data/Aus_Elec_Gen_1980_2018.csv",index_col=0,parse_dates=[0],thousands=',')
elec_df.fillna(0).plot_animated('./fixed-example.gif',period_fmt="%Y",title='Australian Electricity Generation Sources 1980-2018',fixed_max=True,fixed_order=True)
Test6:多子图动态图
import pandas as pd
import pandas_alive
covid_df = pd.read_csv('data/covid19.csv', index_col=0, parse_dates=[0])
animated_line_chart = covid_df.diff().fillna(0).plot_animated(kind='line', period_label=False,add_legend=False)
animated_bar_chart = covid_df.plot_animated(n_visible=10)
pandas_alive.animate_multiple_plots('./example-bar-and-line-chart.gif',
[animated_bar_chart, animated_line_chart], enable_progress_bar=True)
Reference:
[1] 数据可视化: matplotlib绘制动态图及3维动画
[2] 【matplotlib】绘制动态图像
[3] GitHub pandas_alive
|