rggplot2tidyversegganimateggtern

How to animate a ternary plot in R


I am trying to animate a ternary plot in R with gganimate and I am facing into a wall.

library(tidyverse)
library(gganimate)
library(ggtern)
#> Registered S3 methods overwritten by 'ggtern':
#>   method           from   
#>   grid.draw.ggplot ggplot2
#>   plot.ggplot      ggplot2
#>   print.ggplot     ggplot2
#> --
#> Remember to cite, run citation(package = 'ggtern') for further info.
#> --
#> 
#> Attaching package: 'ggtern'
#> The following objects are masked from 'package:ggplot2':
#> 
#>     aes, annotate, ggplot, ggplot_build, ggplot_gtable, ggplotGrob,
#>     ggsave, layer_data, theme_bw, theme_classic, theme_dark,
#>     theme_gray, theme_light, theme_linedraw, theme_minimal, theme_void

data=tibble(x=runif(200),  y = runif(200),  z = runif(200), time=rep(seq(1:10),20))

ggtern(data, aes(x,y,z)) +
  geom_point() +
  theme_rgbw() +
  stat_density_tern(geom = 'polygon',
                    aes(fill  = ..level..,
                        alpha = ..level..), bdl=0.001) +
    scale_fill_gradient(low = "blue",high = "red")  +
  guides(color = "none", fill = "none", alpha = "none") 
#> Warning: Removed 1 rows containing non-finite values (StatDensityTern).

Created on 2022-11-04 with reprex v2.0.2

This is the part of my code that fails. I want to have the points moving at each time point.

ggtern(data, aes(x,y,z)) +
  geom_point() +
  theme_rgbw() +
  stat_density_tern(geom = 'polygon',
                    aes(fill  = ..level..,
                        alpha = ..level..), bdl=0.001) +
    scale_fill_gradient(low = "blue",high = "red")  +
  guides(color = "none", fill = "none", alpha = "none") +
transition_states(transition_length = 1, time)

Solution

  • There is a problem getting ggtern to work with gganimate (see this unanswered stack overflow question).

    Of course, it remains possible to create a ggplot animation the old-fashioned way: write a bunch of png files and stitch them together into a png file using magick:

    library(tidyverse)
    library(gganimate)
    library(ggtern)
    library(magick)
    
    data = tibble(x=runif(400),  y = runif(400),  
                z = runif(400), time = rep(seq(1:20), 20))
    
    
    for(i in 1:20) {
      p <- ggtern(data[data$time == i, ], aes(x, y, z)) +
        geom_point() +
        theme_rgbw() +
        stat_density_tern(geom = 'polygon',
                          aes(fill = ..level.., alpha = ..level..), bdl = 0.001) +
        scale_fill_gradient(low = "blue",high = "red")  +
        guides(color = "none", fill = "none", alpha = "none") 
      
      ggsave(paste0('ggtern', i, '.png'), p)
    }
    
    list.files(pattern = 'ggtern\\d+\\.png', full.names = TRUE) %>% 
      image_read() %>% 
      image_join() %>% 
      image_animate(fps=4) %>% 
      image_write("ggtern.gif") 
    

    Now we have the following file:

    ggtern.gif

    enter image description here