tracé gganimate où les points restent et la ligne s'estompe

11

Voici un exemple reproductible d'une intrigue statique, que je veux animer (je veux montrer comment se comporte un échantillonneur MCMC).

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()

entrez la description de l'image ici

Ce que j'aimerais voir, c'est que les points soient visibles lorsqu'ils sont dessinés et un peu décolorés (c'est-à-dire que l'alpha passe, par exemple, de 1 à 0,3) par la suite, alors qu'il y aurait une ligne qui ne montrerait que l'histoire récente (et, idéalement, s'estompe montrant la histoire la plus récente la moins fanée et plus de quelques pas en arrière totalement disparue)

Ce qui suit réalise plus ou moins ce que je veux pour mes points (donc dans un sens, je veux juste ajouter des lignes de fondu à cela en connectant les derniers points - des points s'estompant plus lentement sur certaines images seraient encore plus agréables):

ggplot(data=plot_data,
       aes(x=y, y=x)) +
  geom_point() +
  transition_time(time) +
  shadow_mark(past = T, future=F, alpha=0.3)

Graphique montrant comment les points devraient s'estomper

Ce qui me pose problème, c'est comment ajouter deux comportements différents pour deux géomètres, par exemple le point et la ligne. Par exemple, ci-dessous, les points disparaissent (je ne veux pas qu'ils) et les lignes ne s'estompent pas (je veux qu'ils).

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) 
Björn
la source

Réponses:

17

J'ai eu du mal à utiliser les shadow_*fonctions intégrées pour contrôler plus d'un comportement à la fois; il semblait simplement appliquer la plus récente. (Utilisation de gganimate 1.0.3.9000)

Une façon de contourner ce problème consiste à calculer les transitions manuellement. Par exemple, nous pourrions copier les données 100 fois, une copie pour chaque image, puis spécifier séparément l'alpha pour notre couche de points et l'alpha pour notre couche de segment.

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)

entrez la description de l'image ici

(Pour ce rendu, je l'ai enveloppé animate( [everything above], width = 600, height = 400, type = "cairo"))

Jon Spring
la source
1
Merci beaucoup. Un problème mineur dans votre réponse: point_alpha = ... & segment_alpha = ... doivent être à l'intérieur du mutate (...). Modifié la réponse en conséquence.
Björn