You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib制作多线图GIF动画时固定各线条颜色的解决方案

问题背景

尝试将二维NumPy数组绘制为多线图,使用的测试数据如下:

data = np.array([[1,2,3,4,5,6],[2,3,4,5,6,7],[2,3,4,5,6,7],[2,3,4,5,6,7]])

现有代码可正常运行,但存在异常:生成的GIF动画每一帧都会自动变更线条颜色。需要实现两个目标:

  • 每一列对应的线条在所有动画帧中保持固定专属颜色
  • 找到更简便的线条固定随机颜色设置方式

现有实现代码如下(存在两处笔误:rage应为range,np.array入参缺少外层包裹方括号;还有一处逻辑错误:ArtistAnimation入参传了单帧对象而非全帧列表):

import gif
from matplotlib import pyplot as plt, animation
ims = []
gif.options.matplotlib["dpi"] = 100
fig, axs = plt.subplots(2, 2)
for i in range(0,5):
    ...    
    lines = axs[1, 0].plot(data) # data会随i取值动态变化
    ...
    final_ims = [im1, im2, im4, text1, text2, text3]
    final_ims.extend(lines)
ani = animation.ArtistAnimation(fig, final_ims, interval=200, blit=True,
                                                repeat_delay=1000)
原因说明

帧间线条颜色跳变的核心原因是:每次循环调用ax.plot()时,matplotlib都会新建线条对象,默认从全局颜色循环的起始位置依次取色,不会复用前一帧同位置线条的颜色属性,因此每次重绘都会出现颜色变化。

实现方案

核心逻辑

不要在循环内部新建线条对象,也不要在循环内生成随机颜色。在循环外提前定义好和线条数量一一对应的颜色列表,初始化时就给线条绑定固定颜色,后续帧只更新线条的Y轴数据即可,从根源避免颜色重置。

固定随机色简便生成方式

  • 纯随机色:直接在循环外一次性生成和列数匹配的RGB色值,转换为matplotlib可识别的格式即可
  • 高区分度色:直接调用matplotlib内置的分类色板,比纯随机生成的RGB颜色辨识度更高,不需要手动调参

修正后示例代码

import numpy as np
import gif
from matplotlib import pyplot as plt, animation

# 修正原测试数据的写法问题
data = np.array([[1,2,3,4,5,6],[2,3,4,5,6,7],[2,3,4,5,6,7],[2,3,4,5,6,7]])
n_lines = data.shape[1]

# ---------- 固定颜色生成,三选一即可 ----------
# 方式1:纯随机固定色
# fixed_colors = [f'#{np.random.randint(0, 0xFFFFFF):06x}' for _ in range(n_lines)]
# 方式2:调用matplotlib默认色板(最简便)
fixed_colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
# 线条数超过默认色板长度时自动循环取色
if len(fixed_colors) < n_lines:
    fixed_colors = (fixed_colors * (n_lines // len(fixed_colors) + 1))[:n_lines]
# 方式3:高区分度内置色板(适合线条数较多的场景)
# cmap = plt.colormaps['tab20']
# fixed_colors = [cmap(i) for i in np.linspace(0, 1, n_lines)]
# ---------------------------------------------

gif.options.matplotlib["dpi"] = 100
fig, axs = plt.subplots(2, 2)
target_ax = axs[1, 0]
ims = []

# 初始化第一帧线条,绑定固定颜色
lines = target_ax.plot(data, color=fixed_colors)

for i in range(0,5):
    # 替换为你自己的每帧数据更新逻辑
    current_data = data * (i+1)
    # 直接更新已有线条的数据,不要重复调用plot新建对象
    for line_idx, line in enumerate(lines):
        line.set_ydata(current_data[:, line_idx])
    
    final_ims = [im1, im2, im4, text1, text2, text3]
    final_ims.extend(lines)
    ims.append(final_ims)

# 修正原代码传参错误,传入存储所有帧的ims列表
ani = animation.ArtistAnimation(fig, ims, interval=200, blit=True, repeat_delay=1000)

额外优化:如果不需要blit模式的高性能渲染,也可以用FuncAnimation实现,逻辑更直观,只需要写更新函数修改线条数据和颜色即可,不需要手动维护每帧的artists列表。

内容的提问来源于stack exchange,提问作者Vlad Matao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:21:34