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

Python如何实现Bar Chart Race排序动态条形图的条形相互超越效果

Python实现动态条形图(Bar Chart Race)的条形平滑超越效果

直接重绘实现的问题

直接每帧清空画布后按当前排序重绘条形的方案,在类别排名发生变化时,条形会直接跳转到新的位置,没有平滑移动的过渡效果,无法呈现出条形相互超越的动画过程。

核心实现思路

  • 为每个类别绑定固定的条形实例和专属颜色,排名变化时颜色始终和类别对应,不会出现视觉混淆
  • 在原始数据的相邻时间帧之间插入多组过渡帧,同时对条形的长度、y轴坐标做线性插值,实现排名变化时的平滑移动效果
  • 每帧仅更新已有条形的属性,无需反复清空重绘画布,大幅提升渲染效率

完整可运行代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# 生成原始测试数据
np.random.seed(42) # 固定随机种子方便复现效果
raw_data = np.abs(np.random.randn(200, 3))
categories = ['a', 'b', 'c']
color_map = {'a':'r', 'b':'g', 'c':'b'} # 固定每个类别对应的颜色
df = pd.DataFrame(raw_data, columns=categories)

# 动画参数配置
transition_frames = 10 # 两个原始数据帧之间的过渡帧数量,越大越平滑
total_frames = (len(df)-1) * transition_frames
interval = 20 # 每帧间隔毫秒数

fig, ax = plt.subplots(figsize=(16, 6.5))
ax.set_xlim(0, df.max().max()*1.1) # 固定x轴范围避免跳动
# 初始化条形对象,每个类别对应一个条形
bars = ax.barh(categories, df.iloc[0], color=[color_map[c] for c in categories])

def update(frame_idx):
    # 计算当前过渡帧对应原始数据的前后两个时间点,以及过渡系数t
    raw_idx = frame_idx // transition_frames
    t = (frame_idx % transition_frames) / transition_frames
    
    # 获取前后两个时间点的数值和排序
    prev_vals = df.iloc[raw_idx]
    next_vals = df.iloc[raw_idx+1]
    prev_rank = prev_vals.sort_values(ascending=False).index.tolist()
    next_rank = next_vals.sort_values(ascending=False).index.tolist()
    
    # 对每个类别计算当前帧的数值和y轴位置
    for cat, bar in zip(categories, bars):
        # 数值插值
        current_val = prev_vals[cat] + t*(next_vals[cat] - prev_vals[cat])
        bar.set_width(current_val)
        # y轴位置插值
        prev_y = prev_rank.index(cat)
        next_y = next_rank.index(cat)
        current_y = prev_y + t*(next_y - prev_y)
        bar.set_y(current_y - 0.4) # 条形默认高度是0.8,偏移0.4让条形居中
    
    # 更新y轴刻度为当前排名的类别,过渡到一半时切换刻度标签
    current_rank = [prev_rank[i] if t<0.5 else next_rank[i] for i in range(len(categories))]
    ax.set_yticks(range(len(categories)))
    ax.set_yticklabels(current_rank)
    return bars

ani = animation.FuncAnimation(
    fig,
    update,
    frames=total_frames,
    interval=interval,
    blit=False
)
plt.show()

效果调整说明

  • 修改transition_frames参数可调整过渡平滑度,数值越大超越动画越流畅,可同步调整interval参数控制动画整体播放速度
  • 可自行扩展更多类别、自定义配色、添加条形数值标签、时间戳等装饰元素,适配不同的可视化需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:54:01