I am working with the R programming language. I am trying to follow the instructions from this tutorial over here (https://www.nagraj.net/notes/gifs-in-r/) for animating 'gifs" in R.
Using the built in "mtcars" dataset, I made the two following graphs:
library(ggplot2)
#graph 1
LINES <- data.frame(ind = 1, Startx=c(1,1,1,3,5,6),#horiz lines then vert lines
Starty=c(15,20,35,7,7,7),
Endx=c(3,5,6,3,5,6),
Endy=c(15,20,35,15,20,35))
a = ggplot(data=mtcars, aes(x=wt, y=mpg)) + geom_point()+
geom_segment(aes(x=Startx,y=Starty,xend=Endx,yend=Endy),data=LINES)+
coord_cartesian(ylim=c(9,36),xlim = c(1.5,6.2))
#graph 2
LINES_1 <- data.frame(ind = 2, Startx=c(2,2,2,4,6,7),#horiz lines then vert lines
Starty=c(16,21,36,8,8,8),
Endx=c(4,6,7,4,6,7),
Endy=c(16,21,36,16,21,36))
b = ggplot(data=mtcars, aes(x=wt, y=mpg)) + geom_point()+
geom_segment(aes(x=Startx,y=Starty,xend=Endx,yend=Endy),data=LINES_1)+
coord_cartesian(ylim=c(9,36),xlim = c(1.5,6.2))
Now, I am trying to follow the instructions from the tutorial and turn these two graphs into an "animation gif":
#create joint dataset
Lines_frame = rbind(LINES, LINES_1)
library(magick)
## create a directory to which the images will be written
dir_out <- file.path(tempdir(), "tx-sales")
dir.create(dir_out, recursive = TRUE)
for (y in Lines_frame$ind) {
p <-
Lines_frame %>%
filter(ind == y) %>%
ggplot(aes(mtcars$wt,mtcars$mpg))
theme_minimal() +
labs(x = "wt", y = "mpg")
fp <- file.path(dir_out, paste0(y, ".png"))
ggsave(plot = p,
filename = fp,
device = "png")
}
## list file names and read in
imgs <- list.files(dir_out, full.names = TRUE)
img_list <- lapply(imgs, image_read)
## join the images together
img_joined <- image_join(img_list)
## animate at 2 frames per second
img_animated <- image_animate(img_joined, fps = 2)
## view animated image
img_animated
## save to disk
image_write(image = img_animated,
path = "tx-sales.gif")
But this returns the following error:
Saving 3.55 x 4.2 in image
Error: Aesthetics must be either length 1 or the same as the data (6): x and y
Run `rlang::last_error()` to see where the error occurred.
Can someone please show me what I am doing wrong? Is there an easier way to do this?
Thanks
library(gganimate)
# add an id row so that gganimate knows which line in the first
# frame matches the ones in the 2nd
Lines_frame = rbind(LINES, LINES_1) %>%
group_by(ind) %>% mutate(id = row_number()) %>% ungroup()
ggplot(data=mtcars, aes(x=wt, y=mpg)) + geom_point() +
geom_segment(aes(x=Startx,y=Starty,xend=Endx,yend=Endy, group = id),
data=Lines_frame)+
coord_cartesian(ylim=c(9,36),xlim = c(1.5,6.2)) +
transition_reveal(ind)
There are a few transition options. For instance, you could alternate back and forth between the two states with transition_states
and make the movement tween with a bounce, because why not:
# wrapping in `animate()` to access its parameters, like frames per second (fps)
animate(
ggplot(data=mtcars, aes(x=wt, y=mpg)) + geom_point()+
geom_segment(aes(x=Startx,y=Starty,xend=Endx,yend=Endy),
data=Lines_frame)+
coord_cartesian(ylim=c(9,36),xlim = c(1.5,6.2)) +
transition_states(ind, state_length = 0.2) +
ease_aes('bounce-in'),
fps = 20, nframes = 200, height = 400, width = 600)