如何将两个不同数据集的ggplot动画按相同时间状态合并
gganimate多图层不同数据集动画同步合并问题
我有两个基于不同数据集生成的ggplot动画,一个为geom_path轨迹动画,另一个为geom_point散点动画,希望将二者按相同时间状态同步合并。
效果演示动图如下:

现有R代码
library(ggplot2) library(gganimate) xx=c(1,1) vv=c(-1,0) ep=0.2 L=5 dl=10 s=15 #generate data data<-matrix(0,L*dl,2) data_all<-matrix(0,L*dl*s,2) for(i in 1:L){ for(j in 1:(s*dl)){ data_all[(i-1)*s*dl+j,]=cos(2*ep*(j-1))*xx+sin(2*ep*(j-1))*vv } for(j in 1:dl){ data[(i-1)*dl+j,]=cos(ep*(j-1))*xx+sin(ep*(j-1))*vv if(j==dl){ xx=data[i*dl,] vv=rnorm(2)*4 } } } t<-rep(c(1:L),each=dl) dat=cbind(t,data) dat<-as.data.frame(dat) colnames(dat)=c("t","x1","x2") p1=ggplot(dat,aes(x = x1, y = x2)) + geom_path()+ transition_reveal(t) p1 t2<-rep(c(1:L),each=dl*s) dat_all=cbind(t2,data_all) dat_all<-as.data.frame(dat_all) colnames(dat_all)=c("t","x1","x2") pp=ggplot(dat_all,aes(x = x1, y = x2)) + geom_point() p2 <- pp + transition_states(t, transition_length = 0.1, state_length = 5) p2
解决方案
不需要分开生成两个动画再合并,直接在同一个ggplot对象中为不同geom指定对应数据集,共用同一套时间过渡规则即可实现同步:
- 两个数据集的时间变量已统一命名为
t,天然满足时间刻度对应要求 - 统一使用
transition_states控制全局时间进度,轨迹图层用shadow_mark保留历史路径,实现和原transition_reveal完全等效的效果
修改后的可运行代码如下:
library(ggplot2) library(gganimate) xx=c(1,1) vv=c(-1,0) ep=0.2 L=5 dl=10 s=15 # 生成轨迹数据集 data<-matrix(0,L*dl,2) data_all<-matrix(0,L*dl*s,2) for(i in 1:L){ for(j in 1:(s*dl)){ data_all[(i-1)*s*dl+j,]=cos(2*ep*(j-1))*xx+sin(2*ep*(j-1))*vv } for(j in 1:dl){ data[(i-1)*dl+j,]=cos(ep*(j-1))*xx+sin(ep*(j-1))*vv if(j==dl){ xx=data[i*dl,] vv=rnorm(2)*4 } } } t<-rep(c(1:L),each=dl) dat=cbind(t,data) dat<-as.data.frame(dat) colnames(dat)=c("t","x1","x2") t2<-rep(c(1:L),each=dl*s) dat_all=cbind(t2,data_all) dat_all<-as.data.frame(dat_all) colnames(dat_all)=c("t","x1","x2") # 合并图层生成同步动画 p <- ggplot() + # 轨迹图层指定dat数据集 geom_path(data = dat, aes(x = x1, y = x2), linewidth = 1) + # 散点图层指定dat_all数据集 geom_point(data = dat_all, aes(x = x1, y = x2), color = "red", size = 2) + # 全局统一过渡规则,和原散点动画参数完全一致 transition_states(t, transition_length = 0.1, state_length = 5) + # 仅保留轨迹历史渲染,实现路径逐步显示的效果 shadow_mark(past = TRUE, future = FALSE, layer = 1) # 渲染动画,帧数可根据需求调整 animate(p, nframes = 300, fps = 20)
内容的提问来源于stack exchange,提问作者Xia.Song
相关产品推荐
相关产品推荐

