Search code examples
rgraphicsggplot2gganimate

geom_contour fails in gganimate but works in ggplot2


I have a problem I cannot solve. I am trying to create an animation using gganimate with geom_contour. When I plot the data frame as a single "frame" it works with no problems; however when I add the "frame" aesthetic and try to run it with gganimate, geom_contour fails to work. I am not sure what is happening after googling around as it is the exact same data frame. Additionally it works fine with geom_raster. I have provided a very small example that represents what I am actually trying to do albeit at a smaller scale.

Any help would be appreciated. Thanks!

library(mvtnorm)
library(ggplot2)
library(gganimate) 

 generateLattice <- function(theta,offset,increment){
  dim1 <- c(seq(from=theta[1]-offset,to=theta[1]-increment,by=increment),seq(from=theta[1],to=theta[1]+offset,by=increment))
  dim2 <- c(seq(from=theta[2]-offset,to=theta[2]-increment,by=increment),seq(from=theta[2],to=theta[2]+offset,by=increment))
  lattice <- expand.grid(dim1,dim2)
  return(lattice)
}

testLattice <- generateLattice(c(5,5),10,0.05)
testPDF <- apply(testLattice,1,function(x){
  dmvnorm(x=x,mean=c(5.5,4.5),sigma=matrix(c(1,0.25,0.25,1),2,2))
})
testLattice$PDF <- testPDF
testLattice$iter <- 1

testLattice1 <- generateLattice(c(6,6),10,0.05)
testPDF1 <- apply(testLattice1,1,function(x){
  dmvnorm(x=x,mean=c(5.0,4.75),sigma=matrix(c(0.9,0.15,0.15,1.2),2,2))
})
testLattice1$PDF <- testPDF
testLattice1$iter <- 2

testLatticeGIF <- rbind(testLattice,testLattice1)

ggplot(testLatticeGIF[testLatticeGIF$iter==1,],aes(x=Var1,y=Var2,z=PDF)) +
  geom_contour()

#works
p <- ggplot(testLatticeGIF,aes(x=Var1,y=Var2,fill=PDF,frame=iter)) +
  geom_raster()
gganimate::gg_animate(p)

#fails
p <- ggplot(testLatticeGIF,aes(x=Var1,y=Var2,z=PDF,frame=iter)) +
  geom_contour()
gganimate::gg_animate(p)

Solution

  • The reason is simply that geom_contour() does not know to handle the data in the form that you pass them to it. The following two plots do both not work:

    ggplot(testLatticeGIF,aes(x=Var1,y=Var2,z=PDF)) +
      geom_contour()
    ## Warning message:
    ## Computation failed in `stat_contour()`:
    ## dimensions of 'x', 'y' and 'z' do not match 
    ggplot(testLatticeGIF,aes(x=Var1,y=Var2,z=PDF,colour=iter)) +
      geom_contour()
    ## Warning message:
    ## Computation failed in `stat_contour()`:
    ## dimensions of 'x', 'y' and 'z' do not match 
    

    I often find it helpful to use, say, colour instead of frame. If this does not work, it is a strong hint that the issue is not with gganimate. Here, the problem is that you need to use the group aesthetic such that geom_contour knows which data points belong together:

    ggplot(testLatticeGIF,aes(x=Var1,y=Var2,z=PDF,group=iter,colour=iter)) +
      geom_contour()
    

    enter image description here

    And now it also works with the animation:

    p <- ggplot(testLatticeGIF,aes(x=Var1,y=Var2,z=PDF,group=iter,frame=iter)) +
           geom_contour()
    gganimate::gg_animate(p)
    

    enter image description here