Python 动态图表制作指南:基于 Matplotlib FuncAnimation
使用 Python 的 Matplotlib 库及 FuncAnimation 模块制作动态图表的方法。文章涵盖了环境配置、数据预处理流程,并详细演示了如何分别实现动态折线图、饼图和条形图。内容包括代码修正、参数解释、动画保存方式以及常见问题的解决方案,旨在帮助读者掌握数据动态可视化的核心技术。

使用 Python 的 Matplotlib 库及 FuncAnimation 模块制作动态图表的方法。文章涵盖了环境配置、数据预处理流程,并详细演示了如何分别实现动态折线图、饼图和条形图。内容包括代码修正、参数解释、动画保存方式以及常见问题的解决方案,旨在帮助读者掌握数据动态可视化的核心技术。

在数据科学和可视化领域,静态图表往往难以充分展示随时间变化的趋势。动态图表能够通过动画形式直观地呈现数据的演变过程,帮助受众更深刻地理解数据背后的逻辑。本文将系统讲解如何使用 Python 的 Matplotlib 库及其扩展模块 FuncAnimation 来制作线型图、条形图和饼图的动态效果。
Matplotlib 是 Python 中最流行的开源绘图库,支持生成直方图、功率谱、条形图、散点图等。其 animation 模块提供了强大的动画功能,核心类为 FuncAnimation。
FuncAnimation 的工作原理类似于一个 While 循环:它会在指定的时间间隔内反复调用用户定义的更新函数(update function),在画布上重新绘制目标数据,从而形成动画效果。主要参数包括:
fig: 用于绘制图表的 Figure 对象。func: 以帧索引或时间为输入的更新函数。interval: 帧之间的间隔延迟,单位为毫秒,默认值为 200。确保已安装必要的依赖库:
pip install matplotlib pandas numpy
为了演示动态效果,我们需要一组随时间变化的数据。本例将使用全球传染病传播数据(COVID-19 死亡人数)作为案例。首先加载数据并进行清洗,提取特定国家的数据并转换为适合可视化的格式。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 设置中文字体显示,避免乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'
df = pd.read_csv(url, delimiter=',', header='infer')
# 筛选感兴趣的国家和省份为空的数据
df_interest = df.loc[
df['Country/Region'].isin(['United Kingdom', 'US', 'Italy', 'Germany'])
& df['Province/State'].isna()]
# 重命名索引以便后续处理
df_interest.rename(
index=lambda x: df_interest.at[x, 'Country/Region'], inplace=True)
# 转置数据,使日期成为行索引
df1 = df_interest.transpose()
df1 = df1.drop(['Province/State', 'Country/Region', 'Lat', 'Long'])
# 移除全零的行
df1 = df1.loc[(df1 != 0).any(1)]
# 转换日期格式
df1.index = pd.to_datetime(df1.index)
动态曲线图是最常见的类型,用于展示随时间累积的趋势。关键在于每次更新时只绘制当前时间点之前的数据。
import matplotlib.animation as ani
color = ['red', 'green', 'blue', 'orange']
fig = plt.figure(figsize=(10, 6))
plt.xticks(rotation=45, ha="right", rotation_mode="anchor")
plt.subplots_adjust(bottom=0.2, top=0.9)
plt.ylabel('No of Deaths')
plt.xlabel('Dates')
def build_line_chart(i):
# 清除旧内容,防止重叠
plt.cla()
plt.title(f'Death Trend Over Time')
plt.legend(df1.columns)
# 绘制从开始到第 i 天的数据
p = plt.plot(df1[:i].index, df1[:i].values)
# 设置每条线的颜色
for idx, line in enumerate(p):
if idx < len(color):
line.set_color(color[idx])
animator = ani.FuncAnimation(fig, build_line_chart, interval=100, blit=False)
plt.show()
优化建议: 在 blit=True 模式下,Matplotlib 会仅重绘发生变化的部分,从而提高性能。但在复杂图表中,blit=False 通常更稳定。
饼状图展示了各部分占总体的比例。由于饼图的结构特性,每次循环需要清空坐标轴 (ax.clear()) 并重新计算百分比。
fig, ax = plt.subplots(figsize=(8, 8))
explode = [0.01, 0.01, 0.01, 0.01] # 分离每个切片
def get_pie_chart(i):
ax.clear()
# 获取最新日期的最大值总和
current_max_sum = df1.head(i).max().sum()
def absolute_value(val):
a = np.round(val / 100. * current_max_sum, 0)
return int(a)
# 绘制饼图
plot = df1.head(i).max().plot.pie(
y=df1.columns,
autopct=absolute_value,
label='',
explode=explode,
shadow=True,
ax=ax
)
# 设置标题显示当前日期
date_str = df1.index[min(i, len(df1.index)-1)].strftime('%y-%m-%d')
plot.set_title(f'Total Number of Deaths\n{date_str}', fontsize=12)
animator = ani.FuncAnimation(fig, get_pie_chart, interval=200, blit=False)
plt.show()
条形图适合比较不同类别在同一时间点的数据量。我们可以定义变量来控制水平或垂直方向。
fig = plt.figure(figsize=(10, 6))
bar_type = 'vertical' # 可选 'horizontal' 或 'vertical'
def build_bar_chart(i):
iv = min(i, len(df1.index) - 1)
objects = df1.max().index
y_pos = np.arange(len(objects))
performance = df1.iloc[[iv]].values.tolist()[0]
plt.cla()
if bar_type == 'vertical':
plt.bar(y_pos, performance, align='center', color=['red', 'green', 'blue', 'orange'])
plt.xticks(y_pos, objects)
plt.ylabel('Deaths')
plt.xlabel('Countries')
plt.title(f'Deaths per Country \n {str(df1.index[iv].strftime("%y-%m-%d"))}')
else:
plt.barh(y_pos, performance, align='center', color=['red', 'green', 'blue', 'orange'])
plt.yticks(y_pos, objects)
plt.xlabel('Deaths')
plt.ylabel('Countries')
plt.title(f'Deaths per Country \n {str(df1.index[iv].strftime("%y-%m-%d"))}')
animator = ani.FuncAnimation(fig, build_bar_chart, interval=100, blit=False)
plt.show()
制作完成后,可以使用 save 方法将动画导出为 GIF 或 MP4 格式。注意,导出视频可能需要额外的编码器(如 ffmpeg)。
# 保存为 GIF
animator.save(r'C:\temp\myfirstAnimation.gif', writer='pillow', fps=10)
# 保存为 MP4 (需要安装 ffmpeg)
# animator.save(r'C:\temp\myfirstAnimation.mp4', writer='ffmpeg', fps=10)
plt.rcParams 配置字体,如 SimHei 或 Microsoft YaHei。blit=True 优化,或限制动画帧数。func 轻量高效。通过 Matplotlib 的 FuncAnimation 模块,开发者可以相对轻松地创建专业的动态数据可视化图表。无论是展示疫情趋势、股票波动还是传感器数据,动态图表都能显著提升信息的传达效率。掌握上述基础示例后,您可以进一步结合 Pandas 的高级数据处理能力,构建更加复杂和交互式的可视化应用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online