Animation in the Long Run: Pixar’s Increasing Movie Lengths
This analysis explores the increasing runtime of Pixar films using {ggplot2} for visualization, with enhancements from packages like {ggimage} for embedding movie posters.
#TidyTuesday
{ggimage}
{magick}
{cropcircles}
Author
Aditya Dahiya
Published
March 11, 2025
About the Data
The data for this week’s #TidyTuesday comes from the {pixarfilms} R package by Eric Leung, which compiles information about Pixar films, their box office performance, critical reception, and ratings from sources like Wikipedia. The dataset includes two key files: pixar_films.csv, which details the release date, runtime, and rating of each film, and public_response.csv, which compiles critic and audience scores from platforms such as Rotten Tomatoes, Metacritic, and CinemaScore. Data can be accessed in R using the {tidytuesdayR} package or directly via read_csv(). This dataset offers opportunities to explore rating discrepancies, missing data patterns, and the relationship between box office earnings and film reviews.
Figure 1: Each dot represents a Pixar film, positioned by its release year on the X-axis and its runtime (in minutes) on the Y-axis. The smooth line illustrates the overall trend of increasing film durations over time, with occasional fluctuations. Film posters provide a visual reference for each title. Data sourced from the {pixarfilms} R package, compiled from Wikipedia.
How I made this graphic?
Loading required libraries, data import & creating custom functions.
Code
# Data Import and Wrangling Toolslibrary(tidyverse) # All things tidy# Final plot toolslibrary(scales) # Nice Scales for ggplot2library(fontawesome) # Icons display in ggplot2library(ggtext) # Markdown text support for ggplot2library(showtext) # Display fonts in ggplot2library(colorspace) # Lighten and Darken colours# Other Toolslibrary(ggpattern) # Image patterns in ggplot2 geomslibrary(magick) # Handling imageslibrary(httr) # Downloading images from Google# Using Rpixar_films <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-03-11/pixar_films.csv')public_response <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-03-11/public_response.csv')
Visualization Parameters
Code
# Font for titlesfont_add_google("Playfair Display",family ="title_font") # Font for the captionfont_add_google("Saira Extra Condensed",family ="caption_font") # Font for plot textfont_add_google("Spectral",family ="body_font") showtext_auto()mypal <- paletteer::paletteer_d("rockthemes::zeppelin")mypal2 <- paletteer::paletteer_d("trekcolors::enara2")# A base Colourbg_col <-colorspace::lighten("#BFCFE3FF", 0.8)seecolor::print_color(bg_col)# Colour for highlighted texttext_hil <- mypal[2]seecolor::print_color(text_hil)# Colour for the texttext_col <- mypal[3]seecolor::print_color(text_col)# Define Base Text Sizebts <-90# Caption stuff for the plotsysfonts::font_add(family ="Font Awesome 6 Brands",regular = here::here("docs", "Font Awesome 6 Brands-Regular-400.otf"))github <-""github_username <-"aditya-dahiya"xtwitter <-""xtwitter_username <-"@adityadahiyaias"social_caption_1 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{github};</span> <span style='color: {text_hil}'>{github_username} </span>")social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_hil}'>{xtwitter_username}</span>")plot_caption <-paste0("**Data:** Wikipedia & {pixarfilms}", " | **Code:** ", social_caption_1, " | **Graphics:** ", social_caption_2 )rm(github, github_username, xtwitter, xtwitter_username, social_caption_1, social_caption_2)# Add text to plot-------------------------------------------------plot_title <-"Pixar's Cinematic Growth:\nIncreasing Runtime"plot_subtitle <-"Over the years, Pixar films have increased in duration, reflecting the studio's evolving storytelling approach. This visualization tracks the runtime of all 26 Pixar movies, with each dot representing a film and its corresponding poster. A smooth trend line highlights the overall growth."
# Get a custom google search engine and API key# Tutorial: https://developers.google.com/custom-search/v1/overview# Tutorial 2: https://programmablesearchengine.google.com/# From:https://developers.google.com/custom-search/v1/overview# google_api_key <- "LOAD YOUR GOOGLE API KEY HERE"# From: https://programmablesearchengine.google.com/controlpanel/all# my_cx <- "GET YOUR CUSTOM SEARCH ENGINE ID HERE"# Load necessary packageslibrary(httr)library(magick)# Define function to download and save movie posterdownload_icons <-function(i) { api_key <- google_api_key cx <- my_cx# Build the API request URL url <-paste0("https://www.googleapis.com/customsearch/v1?q=", URLencode(paste0(plotdf$film[i], " movie poster")), "&cx=", cx, "&searchType=image&key=", api_key)# Make the request response <-GET(url) result <-content(response, "parsed")# Get the URL of the first image result image_url <- result$items[[1]]$link magick::image_read(image_url) |>image_resize("x300") |> cropcircles::circle_crop(border_size =3,border_colour = text_hil ) |>image_read() |>image_write( here::here("data_vizs",paste0("temp_pixar_films_", i,".png")) )}for (i in1:nrow(plotdf)) {download_icons(i)}
Reduce filesize and Savings the thumbnail for the webpage
Code
list.files(path ="data_vizs", pattern ="^temp_pixar_films", full.names =TRUE )file.remove(list.files(path ="data_vizs", pattern ="^temp_pixar_films", full.names =TRUE ))# Saving a thumbnaillibrary(magick)# Saving a thumbnail for the webpageimage_read(here::here("data_vizs", "tidy_pixar_films.png")) |>image_resize(geometry ="x400") |>image_write( here::here("data_vizs", "thumbnails", "tidy_pixar_films.png" ) )
Session Info
Code
# Data Import and Wrangling Toolslibrary(tidyverse) # All things tidy# Final plot toolslibrary(scales) # Nice Scales for ggplot2library(fontawesome) # Icons display in ggplot2library(ggtext) # Markdown text support for ggplot2library(showtext) # Display fonts in ggplot2library(colorspace) # Lighten and Darken colourslibrary(ggpattern) # Image patterns in ggplot2 geomslibrary(magick) # Handling imageslibrary(httr) # Downloading images from Googlesessioninfo::session_info()$packages |>as_tibble() |>select(package, version = loadedversion, date, source) |>arrange(package) |> janitor::clean_names(case ="title" ) |> gt::gt() |> gt::opt_interactive(use_search =TRUE ) |> gtExtras::gt_theme_espn()
Table 1: R Packages and their versions used in the creation of this page and graphics