Data Analysis and Visualization of Animation in R

Posted on Mar 9, 2015

Project GitHub | LinkedIn:   Niki   Moritz   Hao-Wei   Matthew   Oren

The skills we demoed here can be learned through taking Data Science with Machine Learning bootcamp with NYC Data Science Academy.

Information about the student and the project.

  1. Contributed by Malcolm Hess

  2. Malcolm attended the pioneer class of the  NYC data Science Academy bootcamp with instructor Vivian Zhang.
  3. This post is based on his research into creating animations in R.



Basic animation in R

About the project.


    The purpose of this project is to look into the animation package in R.  Animated graphs can adds a unique element to data visualization which may provide greater detail than a static graph.  It also serves as a great way to improve the aesthetics of a presentation or report which will help retain a viewer’s attention.


  The goal is to create an animated graph in R.   I also wanted to create an animation with a transparent background so it can potentially be used as a graphic in a video.


Install the package.


This package creates animations in either an HTML, Latex, SWF, Video, or GIF format.  However to save images in GIF format you will need to install ImageMagick. The ImageMagick site is not very friendly and installing it yourself can be a pain.  I suggest you use HomeBrew for a quick and easy installation. {after HomeBrew is installed apply this command from console/terminal}

brew install imagemagick

There can be significant issues with ImageMagic on the Windows OS.  One type of problem people is that the command to use ImageMagick to convert images to GIFs is “convert”, which Windows already has allocated to another function.  So when you run the convert command it pulls up the original function call and not ImageMagick. I myself encountered a different issue where accessing ImageMagic from my console worked fine but it did not work when accessing the console through R.  Creating GIFs in R is a finicky process because it has to go through the unreliable ImageMagic.  All of my code examples here are for creating GIFs, however most of the code is easily converted to HTML by simply changing the function call and the file extension name.

What is an animation?

The most important idea to understand behind animation is that is is essentially a series of static pictures.  Creating an animated graph works the exact same way.  To do this you create the completed graph and then limit the data flow that it can use to plot.  You then iterate through all of the data starting from the beginning to end (or all of the data points if you are animating a line).  The saveGIF command will take all the plots it has seen and then compact them together into a GIF.


ani.options(interval = 0.2, nmax = 50)

t = seq(0,pi,.01)

x = cos(2*t)

y = sin(2*t)

idx = seq(1,length(x),10)

for (i in seq_along(idx)) {



y[seq(idx[i])], pch=15, col='dark green')

ani.pause() }

}, = "circle.gif",

ani.width = 600, ani.height = 600)



Looking at this example, there are a few important parameters to notice. The interval parameter inside of ani.options is the time between frames.  The nmax parameter is the number of steps in a loop (e.g. iterations to create animation frames. The default is 50, I’ve found that if you try to change it seems to always throw up a warning and tell you it reset it to 50. You will notice that inside of the saveGIF command there is a loop that cycles through the length of the data which will creates all of the images.  After each image  the ani.pause() function is used to create the delay between frames.  The ani.pause() function is the interval parameter which is set in the ani.options.

As you can see the results of the a saveGIF function don’t always work.  Your GIFs might have blank frames as this circle GIF does, GIFs can have pure black frames, and it can even have strange ordering where the frames effectively go from image 19 to image 2, then back up to image 20.

t = seq(0,1.1*pi,.01)

x = cos(2*t) * sin(2*t)

y = tan(2*t) * cos(2*t)

while (i <= length(x)) {

frame = 100 + i

filename <- paste("test", frame, ".png", sep="")

png(file=filename, width=550, height=550)


points(x[1:i], y[1:i], pch=15,col='dark green')

i <- i+1 }

system("convert -delay 40 *.png example_1.gif")

hourglass green working

There is more than one way to make a GIF.  Instead of calling the saveGIF command, you can save all of the individual images to the disk.  Then through the system command you tell ImageMagick to convert the PNG files into a GIF.

maxrows <- nrow(cardata) - 4

i<- 1


ani.options(interval = 0.1, nmax=maxrows)

while(i<maxrows) {

g <- ggplot(cardata, aes(x[i],y[i]), alpha = .05) +

xlim(xlimits) + ylim(ylimits) +

geom_point(colour = "tan", size = 2)

m <- geom_point(data=cardata, aes(x[(i+1)],y[(i+1)]),

colour = "tan", size = 3, alpha = .05)

n <- geom_point(data=cardata, aes(x[(i+2)],y[(i+2)]),colour = "tan", size = 4, alpha = .1)

o <- geom_point(data=cardata, aes(x[(i+3)],y[(i+3)]), colour = "tan", size = 5, alpha = .2)

p <- geom_point(data=cardata, aes(x[(i+4)],y[(i+4)]), colour = "tan", size = 6, alpha = .3)

g <- g + m + n + o + p



i<-i+1 } #end of while loop

},#end of first parameter in saveGIF

interval = 0.03, = "car.gif",

ani.width = 600, ani.height = 600)



There are many techniques you can use to make an animation easier to follow.  As an added benefit it also makes it look more polished.  For example you can add a “comet effect”.  This is when a moving object leaves a trail behind it. One way to achieve this is by plotting several consecutive points in the data.  The trailing points ones have increasing transparency (the lower the alpha the more the transparency).  In my chart transparency wasn’t showing well so instead I made each trailing points smaller than the one ahead of it.  This worked for my chart because the speed of the lead data point is really slow, if it had jumped a large distance it would leave behind the other points giving me several frames where I have four separate data points instead one with a tail.


Talking about speed, a lot of my animations are very slow because I wanted them to be smooth.  Typically the slower the animation, the smoother it will look, just don't let it get painfully slow.  The easiest way to speed up an animation is to decrease the interval time (which decreases the amount of time between frames).  The other route to speed up an animation is decreasing the amount of frames you have in your animation.  To achieve this you simply decrease the amount of iterations in your loop.  If you were using a while loop like I did; instead of increasing i by 1 point in every loop you can increase it by 3.  This would triple the speed by decrease the amount of frames in the overall animation.

t = seq(0,1.1*pi,.01)

x = cos(2*t)*(cos(t)^2)

y = sin(2*t)*(sin(t)^2)

df <- data.frame(t,x,y)


g <- ggplot(df, aes(x,y)) +

theme(panel.grid.minor = element_blank(),

panel.grid.major = element_blank(),

line = element_blank(),

panel.background = element_rect(fill = "transparent",colour = NA),

plot.background = element_rect(fill = "transparent",colour = NA)) +

xlim(c(-1, 1)) + ylim(c(-1, 1)) +

geom_point(data=df[1:i,], aes(x,y), colour = "pink", size = 2)

png(file="testfile.png", width=550, height=550, bg = "transparent")



Keep in mind the default background color for a graph is white (grey for ggplot).  White does not mean transparent.  To make a transparent background in ggplot, the panel background and plot background must be filled transparent and color = NA.

While it is not absolutely necessary to get rid of the major and minor panel lines, I suggest you do because they look really ugly and usually do not contribute useful information to your graph.  You can make the transparent GIF by running the saveGIF function on a series of transparent graphs.

i<-1 while (i < length(x)) {

g <- ggplot(df, aes(x,y)) +

theme(panel.grid.minor = element_blank(),

panel.grid.major = element_blank(),

line = element_blank(),

panel.background = element_rect(fill = '#000000',colour = '#000000'),

plot.background = element_rect(fill = '#000000',colour = '#000000')) +

xlim(c(-1, 1)) + ylim(c(-1, 1)) +

geom_point(data=df[1:i,], aes(x,y), colour = "pink", size = 2)

id<- 100 + i

filename <- paste("transptriangle", id, ".png", sep="")

png(file=filename, width=550, height=550, bg = "transparent")


i<-i+1 }

system("convert -delay 40 *.png input2.gif")

system("convert input2.gif -transparent black output2.gif")


saveGIF is even less reliable when making GIFs with transparent backgrounds so I suggest you save all of the images to disk and set the backgrounds to either solid white or solid black.  Use hex code to make sure it is pure white (#ffffff) or black (#000000).  Then with the system command you can use Imagemagick to convert the PNGs into a GIF. You can then run Imagemagick again to make the background for the GIF transparent.

Conclusion Animation in R is easy although it can be quite frustrating to start.  While animated graphs look great they should be used judiciously.  Don't animate graphs just because you can.  If the animated graph does not help highlight useful information than it is usually better to leave the graph as a static image. It is important to be aware of the speed and cleanliness of the graph.  Try to declare axis values if you can because if you do not, the default axis values may change, causing the data points to jump around.   If your graph is too fast it can look clunky but if it is too slow viewers will get bored watching it.  There will be plenty of trial and error to working towards the best settings for a particular data set. Lastly, I strongly suggest making animations the HTM format.  After having found many issues with the saveGIF function and ImageMagic I do not recommend it’s use.  Only use the GIF format when you have to.

About Author

Related Articles

Leave a Comment

No comments found.

View Posts by Categories

Our Recent Popular Posts

View Posts by Tags

#python #trainwithnycdsa 2019 2020 Revenue 3-points agriculture air quality airbnb airline alcohol Alex Baransky algorithm alumni Alumni Interview Alumni Reviews Alumni Spotlight alumni story Alumnus ames dataset ames housing dataset apartment rent API Application artist aws bank loans beautiful soup Best Bootcamp Best Data Science 2019 Best Data Science Bootcamp Best Data Science Bootcamp 2020 Best Ranked Big Data Book Launch Book-Signing bootcamp Bootcamp Alumni Bootcamp Prep boston safety Bundles cake recipe California Cancer Research capstone car price Career Career Day citibike classic cars classpass clustering Coding Course Demo Course Report covid 19 credit credit card crime frequency crops D3.js data data analysis Data Analyst data analytics data for tripadvisor reviews data science Data Science Academy Data Science Bootcamp Data science jobs Data Science Reviews Data Scientist Data Scientist Jobs data visualization database Deep Learning Demo Day Discount disney dplyr drug data e-commerce economy employee employee burnout employer networking environment feature engineering Finance Financial Data Science fitness studio Flask flight delay gbm Get Hired ggplot2 googleVis H20 Hadoop hallmark holiday movie happiness healthcare frauds higgs boson Hiring hiring partner events Hiring Partners hotels housing housing data housing predictions housing price hy-vee Income Industry Experts Injuries Instructor Blog Instructor Interview insurance italki Job Job Placement Jobs Jon Krohn JP Morgan Chase Kaggle Kickstarter las vegas airport lasso regression Lead Data Scienctist Lead Data Scientist leaflet league linear regression Logistic Regression machine learning Maps market matplotlib Medical Research Meet the team meetup methal health miami beach movie music Napoli NBA netflix Networking neural network Neural networks New Courses NHL nlp NYC NYC Data Science nyc data science academy NYC Open Data nyc property NYCDSA NYCDSA Alumni Online Online Bootcamp Online Training Open Data painter pandas Part-time performance phoenix pollutants Portfolio Development precision measurement prediction Prework Programming public safety PwC python Python Data Analysis python machine learning python scrapy python web scraping python webscraping Python Workshop R R Data Analysis R language R Programming R Shiny r studio R Visualization R Workshop R-bloggers random forest Ranking recommendation recommendation system regression Remote remote data science bootcamp Scrapy scrapy visualization seaborn seafood type Selenium sentiment analysis sentiment classification Shiny Shiny Dashboard Spark Special Special Summer Sports statistics streaming Student Interview Student Showcase SVM Switchup Tableau teachers team team performance TensorFlow Testimonial tf-idf Top Data Science Bootcamp Top manufacturing companies Transfers tweets twitter videos visualization wallstreet wallstreetbets web scraping Weekend Course What to expect whiskey whiskeyadvocate wildfire word cloud word2vec XGBoost yelp youtube trending ZORI