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

如何用gganimate实现geom_bar/geom_col填充区块的移动动画?

问题描述

我在同一数据框中通过Group变量区分两类数据状态:

  • Original状态:对应10个等级的不等计数数据
  • Transformed Internal状态:由原始数据归一化得到的等计数数据

尝试用gganimate实现从原始数据到归一化数据的无缝过渡动画,但两种方案均失败:

  • 使用geom_bar时,仅Rank 1过渡正常,其余等级过渡异常
  • 使用geom_tile时,过渡效果差,且第二个状态的柱状图显示异常

相关代码与数据

原始状态绘图代码

df |> 
  filter(Group == "Original") |> 
  ggplot(aes(original_rank, count)) +
  geom_bar(stat = "identity", aes(fill = transformed_rank)) +
  scale_fill_manual(values = RColorBrewer::brewer.pal(10, "RdYlGn"),
                    name = "Original Rank",
                    guide = guide_legend(byrow = TRUE))

转换后状态绘图代码

df |> 
  filter(Group == "Transformed Internal") |> 
  ggplot(aes(original_rank, count)) +
  geom_bar(stat = "identity", aes(fill = transformed_rank)) +
  scale_fill_manual(values = RColorBrewer::brewer.pal(10, "RdYlGn"),
                    name = "Original Rank",
                    guide = guide_legend(byrow = TRUE))

尝试的geom_bar动画代码

df |> 
  ggplot(aes(original_rank, count)) +
  geom_bar(stat = "identity", aes(fill = transformed_rank)) +
  scale_fill_manual(values = RColorBrewer::brewer.pal(10, "RdYlGn"),
                    name = "Original Rank",
                    guide = guide_legend(byrow = TRUE)) +
  labs(title = "{closest_state}") +
  transition_states(Group)

尝试的geom_tile动画代码

df |> 
  ggplot(aes(original_rank, count, fill = transformed_rank)) +
  geom_tile(aes(y = count/2, height = count, width = 0.9)) +
  scale_fill_manual(values = RColorBrewer::brewer.pal(10, "RdYlGn"),
                    name = "IMD 2019 Decile",
                    guide = guide_legend(byrow = TRUE)) +
  labs(title = "{closest_state}") +
  transition_states(Group)

示例数据

df <- structure(list(original_rank = structure(c(1L, 2L, 3L, 4L, 4L, 
5L, 5L, 6L, 6L, 6L, 7L, 7L, 8L, 8L, 9L, 9L, 9L, 10L, 10L, 1L, 
1L, 1L, 1L, 2L, 2L, 3L, 3L, 4L, 5L, 5L, 6L, 6L, 7L, 7L, 8L, 9L, 
9L, 10L), levels = c("1", "2", "3", "4", "5", "6", "7", "8", 
"9", "10"), class = "factor"), transformed_rank = structure(c(1L, 
2L, 3L, 4L, 4L, 5L, 5L, 6L, 6L, 6L, 7L, 7L, 8L, 8L, 9L, 9L, 9L, 
10L, 10L, 1L, 2L, 3L, 4L, 4L, 5L, 5L, 6L, 6L, 6L, 7L, 7L, 8L, 
8L, 9L, 9L, 9L, 10L, 10L), levels = c("1", "2", "3", "4", "5", 
"6", "7", "8", "9", "10"), class = "factor"), count = c(179L, 
2562L, 5886L, 1468L, 9084L, 1091L, 8698L, 1463L, 10170L, 5367L, 
4699L, 6707L, 3381L, 6510L, 3642L, 10054L, 1663L, 8398L, 10165L, 
179L, 2562L, 5886L, 1468L, 9084L, 1091L, 8698L, 1463L, 10170L, 
5367L, 4699L, 6707L, 3381L, 6510L, 3642L, 10054L, 1663L, 8398L, 
10165L), Group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), levels = c("Original", 
"Transformed Internal"), class = "factor")), row.names = c(NA, 
-38L), class = c("tbl_df", "tbl", "data.Frame"))

解决方案

问题根源在于原数据中部分original_rank在同一个Group下存在多行记录,导致geom_bar绘制时自动堆叠,transition_states无法正确匹配两个状态下的对应柱子。解决步骤如下:

  1. 聚合数据:对每个Group和original_rank的计数求和,确保每个等级在每个状态下只有一行记录
  2. 优化动画参数:使用transition_states的transition_length和state_length控制过渡时长,搭配ease_aes让过渡更平滑

完整代码

library(dplyr)
library(ggplot2)
library(gganimate)
library(RColorBrewer)

# 聚合数据,消除同一等级的多行堆叠问题
df_agg <- df |>
  group_by(Group, original_rank, transformed_rank) |>
  summarise(count = sum(count), .groups = "drop")

# 生成平滑过渡动画
df_agg |>
  ggplot(aes(x = original_rank, y = count, fill = transformed_rank)) +
  geom_col(width = 0.9) + # 替代geom_bar(stat="identity"),效果一致更直观
  scale_fill_manual(values = brewer.pal(10, "RdYlGn"),
                    name = "Original Rank",
                    guide = guide_legend(byrow = TRUE)) +
  labs(title = "{closest_state}") +
  transition_states(Group, transition_length = 2, state_length = 1) +
  ease_aes("cubic-in-out")

说明

  • 聚合后的数据让transition_states能准确识别两个状态下的对应柱子,实现所有等级的平滑过渡
  • ease_aes("cubic-in-out")设置了缓动效果,让动画过渡更自然
  • 若Transformed Internal状态确实是等计数,聚合后该状态下所有original_rank的count值会相等,动画将清晰展示从不等高到等高的变化效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 17:08:10