plot gganimate tempat poin tetap dan garis memudar

11

Berikut ini adalah contoh plot statis yang dapat direproduksi, yang ingin saya menghidupkan (saya ingin menunjukkan bagaimana MCMC sampler berperilaku).

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

masukkan deskripsi gambar di sini

Yang ingin saya lihat adalah titik-titik yang terlihat ketika mereka digambar dan sedikit memudar (yaitu alpha berubah dari misalnya 1 menjadi 0,3) setelahnya, sementara akan ada garis yang hanya menunjukkan sejarah terakhir (dan idealnya memudar menunjukkan paling baru sejarah paling tidak pudar dan lebih dari beberapa langkah kembali benar-benar menghilang).

Berikut ini mencapai kurang lebih apa yang saya inginkan untuk poin saya (jadi dalam arti saya hanya ingin menambahkan garis fading ke ini menghubungkan beberapa poin terakhir - poin memudar lebih lambat di beberapa frame akan lebih baik):

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

Plot menunjukkan bagaimana poin harus memudar

Yang saya perjuangkan adalah bagaimana menambahkan dua perilaku yang berbeda untuk dua geom, misalnya titik dan garis. Misal di bawah, poin hilang (saya tidak ingin mereka) dan garis tidak memudar (saya ingin mereka).

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
sumber

Jawaban:

17

Saya mengalami masalah dalam menggunakan shadow_*fungsi bawaan untuk mengontrol lebih dari satu perilaku sekaligus; sepertinya hanya menerapkan yang terbaru. (Menggunakan gganimate 1.0.3.9000)

Salah satu cara untuk mengatasi ini adalah dengan menghitung transisi secara manual. Misalnya, kita dapat menyalin data 100 kali, satu salinan untuk setiap frame, dan kemudian menentukan alpha untuk lapisan poin kami dan alpha untuk lapisan segmen kami secara terpisah.

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)

masukkan deskripsi gambar di sini

(Untuk render ini, saya membungkusnya animate( [everything above], width = 600, height = 400, type = "cairo"))

Jon Spring
sumber
1
Terima kasih banyak. Satu masalah kecil dalam jawaban Anda: point_alpha = ... & segment_alpha = ... harus ada di dalam mutate (...). Dimodifikasi jawabannya sesuai.
Björn