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
相关产品推荐
相关产品推荐

