trama gganimate donde los puntos permanecen y la línea se desvanece

11

Aquí hay un ejemplo reproducible de una trama estática, que quiero animar (quiero mostrar cómo se comporta un muestreador 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()

ingrese la descripción de la imagen aquí

Lo que me gustaría ver es que los puntos sean visibles cuando se dibujan y se desvanecen un poco (es decir, el alfa va, por ejemplo, de 1 a 0.3) después, mientras que habría una línea que solo muestra el historial reciente (e idealmente se desvanece mostrando el la historia más reciente, el menos desvanecido y más de unos pocos pasos atrás desapareciendo por completo).

Lo siguiente logra más o menos lo que quiero para mis puntos (por lo que, en cierto sentido, solo quiero agregar líneas de desvanecimiento para conectar los últimos puntos; los puntos que se desvanecen más lentamente en algunos cuadros serían aún mejores):

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

Gráfico que muestra cómo deberían desvanecerse los puntos

Con lo que estoy luchando es cómo agregar dos comportamientos diferentes para dos geoms, por ejemplo, punto y línea. Por ejemplo, en la parte inferior los puntos desaparecen (no quiero que lo hagan) y las líneas no se desvanecen (quiero que lo hagan).

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
fuente

Respuestas:

17

Tuve problemas para usar las shadow_*funciones integradas para controlar más de un comportamiento a la vez; parecía aplicar solo el más reciente. (Usando gganimate 1.0.3.9000)

Una forma de evitar esto es calcular las transiciones manualmente. Por ejemplo, podríamos copiar los datos 100 veces, una copia para cada cuadro, y luego especificar el alfa para nuestra capa de puntos y el alfa para nuestra capa de segmento por separado.

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)

ingrese la descripción de la imagen aquí

(Para este render, lo envolví animate( [everything above], width = 600, height = 400, type = "cairo"))

Jon Spring
fuente
1
Muchas gracias. Un problema menor en su respuesta: point_alpha = ... & segmento_alfa = ... necesita estar dentro de la mutación (...). Modificó la respuesta en consecuencia.
Björn