-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Data Structures
-
Section 4: Data Manipulation
-
Section 5: Visualization and Statistics
-
Section 6: Advanced R
-
Section 7: Practical Projects
-
Section 8: Interview Practice
-
Section 9: More Practice Exercises
-
Section 10: Shiny Apps in Depth
-
Section 11: More Data Wrangling
-
Section 12: Tidyverse Deep Dive
-
Section 13: Statistical Modeling Deep Dive
-
Section 14: Machine Learning in R
-
Section 15: R Visualization Deep Dive
-
Section 16: R Package Development Deep Dive
-
Section 17: R for Reproducible Research
-
Section 18: R and Databases
-
Section 19: R Performance Optimization
-
Section 20: Bioinformatics and Specialized R
-
Section 21: More Shiny Practice
-
Section 22: More Practice Exercises
-
Section 23: R Data Structures Deep Dive
-
Section 24: More Interview and Review
-
Section 25: R for Business Analytics
-
Section 26: R Text Mining and NLP
-
Section 27: R Spatial Data Analysis
-
Section 28: R Deep Learning
-
Section 29: Advanced Statistical Techniques
-
Section 30: R Object Systems Deep Dive
-
Section 31: R Environments and Metaprogramming
-
Section 32: R for Finance
-
Section 33: R for Clinical and Health Data
-
Section 34: More Shiny Advanced Practice
-
Section 35: R Data Cleaning Deep Dive
-
Section 36: R Reporting Automation
-
Section 37: More Practical Projects Round 2
-
Section 38: R Ecosystem and Career
-
Section 39: More Visualization Practice
-
Section 40: R for Experimentation
-
Section 41: R for Genomics and Bioinformatics Deep Dive
-
Section 42: R for Marketing Analytics
-
Section 43: R Data Import/Export Deep Dive
-
Section 44: R String Processing Deep Dive
-
Section 45: R for Actuarial and Insurance Analytics
-
Section 46: R Testing and Quality Assurance Deep Dive
-
Section 47: R Version Control and Collaboration
-
Section 48: R Advanced Functional Programming
-
Section 49: R for Supply Chain and Operations
-
Section 50: More Practice Exercises Round 3
-
Section 51: R Dashboards and BI Integration
-
Section 52: R Data Governance and Ethics
-
Section 53: More Modeling Practice
-
Section 54: R Final Capstone Projects
-
Section 55: R for Sports Analytics
-
Section 56: More Interview Practice Round 2
-
Section 57: R Networking and APIs
-
Section 58: R for Environmental Science
-
Section 59: R Notebook and Documentation Practices
-
Section 60: More Data Wrangling Mastery
-
Section 61: R for A/B Testing at Scale
-
Section 62: R Package Ecosystem Deep Dive
156: Practice Exercise: Building an Animated Visualization with gganimate
Static plots are the bread and butter of R, but sometimes a still image doesn't capture the "story" of the data—especially when you're dealing with trends over time. That's where gganimate comes in. It's essentially a wrapper for ggplot2 that lets us treat time or categories as an animation frame.
For this lesson, I want us to build a visualization that tracks the hypothetical temperature trends of three different cities over a season. It's a simple scenario, but it'll let us touch on the most critical parts of the package: transitions, enter/exit animations, and the dreaded "jumpy line" bug.
Setting up our weather data
I'm going to generate a quick synthetic dataset. In a real project, you'd be loading a CSV here, but for this exercise, I want to make sure we have a clean time series to work with.
library(ggplot2)
library(gganimate)
library(dplyr)
# Creating a fake dataset of 90 days for 3 cities
set.seed(42)
days <- 1:90
cities <- c("New York", "London", "Tokyo")
weather_data <- expand.grid(Day = days, City = cities) %>%
group_by(City) %>%
mutate(Temp = cumsum(rnorm(90, mean = 0.1, sd = 2)) + runif(1, 10, 20))
# Let's peek at it
head(weather_data)
Mapping the static foundation
Before we touch any animation functions, we have to build a standard ggplot. If the static plot doesn't look right, the animation will be a nightmare to debug. I'll start with a simple line chart. I'm using geom_line because we want to see the trajectory of the temperature.
# The base plot
p <- ggplot(weather_data, aes(x = Day, y = Temp, color = City)) +
geom_line() +
labs(title = "Temperature Trend: Day {frame_time}",
x = "Day of Season",
y = "Temperature (C)") +
theme_minimal()
p
Adding the dimension of time
Now we turn this into an animation. The most common function you'll use is transition_time(). This tells R, "Instead of showing all the data at once, slice it by this variable and move through it sequentially."
I'll also add ease_aes(). Without it, the animation can feel robotic—linear movement is boring. ease_aes('cubic-in-out') makes the transition feel more organic, like it's accelerating and decelerating naturally.
anim <- p +
transition_time(Day) +
ease_aes('cubic-in-out')
# To view it, we call animate()
animate(anim, nframes = 100, fps = 10)
Correcting the "Jumpy Line" glitch
If you ran the code above, you might have noticed something weird: the lines aren't "drawing" themselves from left to right. Instead, they might be flickering or jumping around. I've made this mistake a dozen times.
The problem is that gganimate doesn't automatically know which points belong to which line when it's animating the transition. It treats every point as an individual entity. To fix this, we need to explicitly tell the aes() mapping that the lines are grouped by City.
# The Fix: Adding 'group = City' inside aes()
p_fixed <- ggplot(weather_data, aes(x = Day, y = Temp, color = City, group = City)) +
geom_line() +
labs(title = "Temperature Trend: Day {frame_time}",
x = "Day of Season",
y = "Temperature (C)") +
theme_minimal()
anim_fixed <- p_fixed +
transition_time(Day) +
ease_aes('cubic-in-out')
animate(anim_fixed, nframes = 100, fps = 10)
Polishing the motion
To wrap this up, I want the lines to feel a bit more "alive." I'll add shadow_wake()` and exit_fade()`. The wake creates a trail behind the leading edge of the line, which helps the viewer track the movement. It's a small detail, but it's the difference between a "chart that moves" and a "professional visualization."
final_anim <- p_fixed +
transition_time(Day) +
shadow_wake(wake_length = 0.1, alpha = 0.4) +
ease_aes('cubic-in-out')
animate(final_anim, nframes = 100, fps = 10)
📋 Practical Task
Exercise: Visualizing Regional Website Traffic Spikes
Your goal is to create an animated line chart showing website traffic for three different regions (North America, Europe, and Asia) over a 30-day period.
Requirements:
- Generate a data frame with columns:
Day(1 to 30),Region(NA, EU, Asia), andVisitors(randomly generated numbers between 100 and 1000). - Create a
ggplotusinggeom_line. Ensure you use thegroupaesthetic to prevent the lines from jumping during animation. - Use
transition_time(Day)to animate the growth of the traffic. - Include a dynamic title using
{frame_time}to show which day is currently being displayed. - Add a
shadow_wakeeffect to the lines to make the movement smoother. - Render the final animation with
nframes = 60andfps = 12.
There are no comments for now.