Create animated charts for data visualization using R

Many traditional methods of data visualization are now being replaced by new methods. Other than showing several graphs or a stacked graph to present the variation of your data, it would be much more understandable and interesting if you could visualize it as an animated diagram. Here, I have created a lollipop chart animation. In this example I am using the weekly number of leishmaniasis patients in each district of Sri Lanka from Jan 2014 – Dec 2015.

Loading packages (pacman install and load all the packages)

ggplot2 – for charts; gganimate – to animate the charts; rio – to import data; dplyr & tidyr – to arrange and tidy the data; gifski – To render the animation

pacman::p_load(ggplot2, gganimate, rio, tidyr, dplyr, gifski)

#pacman (package manager install and load all the packages.)

Importing data and checking

clTemp <- import("C:/Users/hp/Documents/MEGAsync/TWData/cltdata.csv")
cltraw <- clTemp[1:103] # selecting the exact range of data from the imported data sheets. 

head(cltraw)[1:4] # Checking first four columns of the data frame
##       District 3/1/2014 10/1/2014 17/01/2014
## 1      Colombo        0         0          0
## 2      Gampaha        1         0          0
## 3     Kalutara        0         0          0
## 4        Kandy        0         0          0
## 5       Matale        0         0          0
## 6 Nuwara Eliya        0         0          0

In the data frame, a week is a column. But we need to get all the weeks as a row of a new column called week. This is done by pivot_longer function (gather() is another possible function for this. But that has been stopped developing and may not be available in coming versions. So I am using pivot function)

Lets pivot

cltpiv <- pivot_longer(cltraw, cols = 2:103) 


cltpiv %>% tail(10)
## # A tibble: 10 x 3
##    District name       value
##    <chr>    <chr>      <int>
##  1 Kalmune  23/10/2015    NA
##  2 Kalmune  30/10/2015    NA
##  3 Kalmune  6/11/2015     NA
##  4 Kalmune  13/11/2015    NA
##  5 Kalmune  20/11/2015    NA
##  6 Kalmune  27/11/2015    NA
##  7 Kalmune  4/12/2015     NA
##  8 Kalmune  11/12/2015    NA
##  9 Kalmune  18/12/2015    NA
## 10 Kalmune  25/12/2015    NA

I’ve included data for all 26 districts. So for 26*102 should be the num of rows

nrow(cltpiv)
## [1] 2652

Pivoting converts the variable into characters. So I will create a Week clumn separately and cbind it to the data frame.

startDate <- as.Date("2014-01-03")

Weekraw <- seq(startDate, by="1 week", length.out=102) 

Week <- rep(Weekraw, times = 26) # coz in the long format need one repitition for each district

tail(Week) # To check if the data is fitting
## [1] "2015-11-06" "2015-11-13" "2015-11-20" "2015-11-27" "2015-12-04"
## [6] "2015-12-11"

Lets combine Week to “cltar”

clt_bound <- cbind(cltpiv, Week)

cltar <- clt_bound %>% select(-name) #remove unnecessary column

In this data set missing values means the number of patients = 0

Lets convert all the “na” s to 0

cltar[is.na(cltar)] <- 0

head(cltar)
##   District value       Week
## 1  Colombo     0 2014-01-03
## 2  Colombo     0 2014-01-10
## 3  Colombo     0 2014-01-17
## 4  Colombo     0 2014-01-24
## 5  Colombo     0 2014-01-31
## 6  Colombo     0 2014-02-07
clt <- cltar # for the ease of calling

colnames(clt) <- c("District", "Patients", "Week") # Renaming columns

Creating the basic plot

p <- ggplot(clt,
       aes(x=District, y=Patients, label = District, color = District)) + 
  geom_point(stat = "identity", size = 4) + 
  geom_segment(aes(
    y = 26,
    x = District,
    yend = Patients,
    xend = District)
    ) 

Shifting axis and adding text to bars

p <- ggplot(clt,
       aes(x=District, y=Patients, label = District, color = District)) + 
  geom_point(stat = "identity", size = 4) + 
  geom_segment(aes(
    y = 26,
    x = District,
    yend = Patients,
    xend = District)
    ) + 
  geom_text(color = "block", size = 4) + #adding text to bar
  coord_flip() # shifting axis

Making the animation

p <- ggplot(clt,
       aes(x=District, y=Patients, label = District, color = District)) + 
  geom_point(stat = "identity", size = 4) + 
  geom_segment(aes(
    y = 26,
    x = District,
    yend = Patients,
    xend = District)
    ) + 
  geom_text(color = "block", size = 4) + #adding text to bar
  coord_flip() + # shifting axis
  theme(legend.position = "none") + #removing legend
    labs (title = "Week: {frame_time}", x= "Week", y = "Patients") + # The animation codes starts here
    transition_time(Week)
  ease_aes('linear')
## <ggproto object: Class EaseAes, gg>
##     aes_names: 
##     aesthetics: 
##     default: linear
##     get_ease: function
##     super:  <ggproto object: Class EaseAes, gg>

Following code renders the animation and give the specifications to animation. You can change duration and the size of the animation by changing the “animate” function. Note that you could use anim_save(“output.gif”) to save the animation as a GIF file. I have removed it as it brings an error when knitting the markdown file.

animate(p, duration = 40, fps = 20, width = 500, height = 500, renderer = gifski_renderer())

# anim_save("output.gif")