Skip to content

Instantly share code, notes, and snippets.

@AdamSpannbauer
Created December 13, 2017 16:20
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AdamSpannbauer/6fda7fd5cc6b876eb581767ec8170e03 to your computer and use it in GitHub Desktop.
Save AdamSpannbauer/6fda7fd5cc6b876eb581767ec8170e03 to your computer and use it in GitHub Desktop.
library(data.table)
library(gganimate)
library(ggplot2)
#toy example data
dt = data.table(time=1:10, x=round(runif(10, 50, 100), 0))
#number of frames per bar
n_frames_per_bar = 20
#create sequence per time (to imitate the bar growing from ground)
split_dt = split(dt, dt$time)
split_dt_fill = lapply(split_dt, function(dti) {
#create sequence of length n per bar for animation
data.table(time=dti$time, x=seq(1, dti$x, length.out = n_frames_per_bar))
})
dt_fill = rbindlist(split_dt_fill)
#id each row as its own frame
dt_fill[,frame := 1:.N]
#once a bar is grown it needs to stay there
#fill in historical bars at full height in future time periods
split_dt_fill2 = split(dt_fill, dt_fill$time)
split_dt_fill2_backfill = lapply(split_dt_fill2, function(dti){
#get time i
time_i = unique(dti$time)
#make bar for time i a different color
dti[,fill := "time i"]
#backfill bar heights if there is history to fill in
if (time_i > 1) {
#get max bar height for all historical bars
backfill_dt = dt_fill[time < time_i,][order(-frame), .SD[1], by=time][,.(time,x)]
#create a row of max height for each frame in time i
split_backfill_dt = split(backfill_dt, backfill_dt$time)
split_backfill_dt = lapply(split_backfill_dt, function(dtj){
data.table(time=dtj$time, x=dtj$x, frame=dti$frame)
})
backfill_dt = rbindlist(split_backfill_dt)
#label fill group for coloring bars
backfill_dt[,fill := "historical"]
out = rbind(dti, backfill_dt)
} else {
out = dti
}
out
})
plot_dt = rbindlist(split_dt_fill2_backfill)
#plot (using gganimate's frame arg in aes)
p = ggplot(plot_dt, aes(x=time, y=x, frame=frame, fill=fill)) +
geom_bar(stat="identity", position = "identity") +
scale_fill_manual(values=c("steelblue", "steelblue1")) +
guides(fill=FALSE) +
labs(x="Time", y="Value", title="")
#create gif (using interval to specify the time per frame)
gganimate(p, title_frame = FALSE, interval = .001)
@AdamSpannbauer
Copy link
Author

this is a preliminary draft. if anyone stumbles across this and has suggestions for improvement feel free to comment the fix

@RMHogervorst
Copy link

As others have said, you should package it! Thanks so much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment