Here is a reproducible example of a static plot, which I want to animate (I want to show how a MCMC sampler behaves).
library(tidyverse)
library(gganimate)
set.seed(1234)
plot_data <- tibble(x=cumsum(rnorm(100)),
y=cumsum(rnorm(100)),
time=1:length(x))
ggplot(data=plot_data,
aes(x=y, y=x)) +
geom_point() + geom_line()
What I'd like to see is the points being visible when they are drawn and a bit faded (i.e. alpha goes from e.g. 1 to 0.3) afterwards, while there would be a line that only shows the recent history (and ideally fades showing the most recent history the least faded and more than a few steps back totally disappearing).
The following achieves more or less what I want for my points (so in a sense I just want to add fading lines to this connecting the last few points - points fading more slowly across some frames would be even nicer):
ggplot(data=plot_data,
aes(x=y, y=x)) +
geom_point() +
transition_time(time) +
shadow_mark(past = T, future=F, alpha=0.3)
What I am struggling with is how to add two different behaviors for two geoms e.g. point and line. E.g. in the below the points disappear (I don't want them to) and the lines do not fade (I want them to).
p <- ggplot(data=plot_data,
aes(x=y, y=x)) +
geom_point() +
transition_time(time) +
shadow_mark(past = T, future=F, alpha=0.3)
p + geom_line() +
transition_reveal(along = time) +
shadow_mark(past = T, future=F, alpha=0.3)
I had trouble using the built-in shadow_*
functions to control more than one behavior at a time; it seemed to just apply the most recent one. (Using gganimate 1.0.3.9000)
One way to get around this is to calculate the transitions manually. For instance, we could copy the data 100 times, one copy for each frame, and then specify the alpha for our points layer and the alpha for our segment layer separately.
plot_data %>%
uncount(100, .id = "frame") %>%
filter(time <= frame) %>%
arrange(frame, time) %>%
group_by(frame) %>%
mutate(x_lag = lag(x),
y_lag = lag(y),
tail = last(time) - time,
# Make the points solid for 1 frame then alpha 0.3
point_alpha = if_else(tail == 0, 1, 0.3),
# Make the lines fade out over 20 frames
segment_alpha = pmax(0, (20-tail)/20)) %>%
ungroup() %>%
ggplot(aes(x=y, y=x, xend = y_lag, yend = x_lag, group = time)) +
geom_segment(aes(alpha = segment_alpha)) +
geom_point(aes(alpha = point_alpha)) +
scale_alpha(range = c(0,1)) +
guides(alpha = F) +
transition_manual(frame)
(For this render, I wrapped it in animate( [everything above], width = 600, height = 400, type = "cairo")
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With