Interactive charts in R and beyond

Nicola Rennie

EdinbR User Group
15 May 2025

About me

Data visualisation specialist, mainly using R, Python, and D3.


Background in statistics, operational research, and data science.


Author of several R packages (mainly for visualisation).


Co-author of Royal Statistical Society’s Best Practices for Data Visualisation guidance.

Grid of R package hex logos



Interactive charts

What do we mean by interaction?

Interactive charts in R

Shiny: build interactive web apps straight from R.

Shiny hex logo

Requires an R server (or shinylive) for deployment to perform computations.

htmlwidgets: use JavaScript visualisation libraries at the R console.

  • plotly (via ggplotly() function)
  • leaflet
  • ggiraph

Just an HTML file, and computations happen in the browser.

Interfacing with other tools outside R

Why is browser-based good?

  • Faster
  • Cheaper
  • Easier to maintain

The rest of this talk…

Effects:

  • Dynamic effects: tooltips, hover effects, crosshairs, …

  • Interaction: dropdowns, check boxes, …

Tools:

  • {ggiraph} R package
  • Interfacing with Observable



{ggiraph}

A tool that allows you to create dynamic {ggplot} graphs

What is ggiraph?

  • R package for making {ggplot2} graphs dynamic
  • Apparently pronounced giraffe

ggiraph package logo

Let’s get some (clean) data!

library(tidyverse)

# Read data
dinosaurs_raw <- read_csv("dinosaurs.csv")

# Data wrangling
dinosaurs <- dinosaurs_raw |>
  select(period, length, name, type) |>
  filter(period != "USA") |>
  mutate(
    period = str_remove(
      period, " million years ago"
    ),
    period = str_remove_all(
      period, "[0-9]"
    ),
    period = str_remove(period, "-"),
    period = str_trim(period),
    length = as.numeric(
      str_remove(length, "m")
    ),
    name = str_to_title(name),
    type = str_to_title(type)
  ) |>
  drop_na() |>
  mutate(
    period = factor(period, levels = c(
      "Late Triassic", "Early Jurassic",
      "Mid Jurassic", "Late Jurassic",
      "Early Cretaceous",
      "Late Cretaceous"
    ))
  )
period length name type
Early Jurassic 8.00 Aardonyx Sauropod
Late Cretaceous 9.00 Abelisaurus Large Theropod
Late Cretaceous 6.00 Achelousaurus Ceratopsian
Late Cretaceous 5.00 Achillobator Large Theropod
Early Cretaceous 12.00 Acrocanthosaurus Large Theropod
Late Cretaceous 15.00 Aegyptosaurus Sauropod
Early Cretaceous 9.00 Afrovenator Large Theropod
Late Jurassic 1.50 Agilisaurus Euornithopod
Late Cretaceous 21.00 Alamosaurus Sauropod
Late Cretaceous 7.00 Albertaceratops Ceratopsian
Late Cretaceous 9.00 Albertosaurus Large Theropod
Late Cretaceous 5.00 Alectrosaurus Large Theropod
Late Cretaceous 6.00 Alioramus Large Theropod
Late Jurassic 12.00 Allosaurus Large Theropod
Late Cretaceous 2.00 Alvarezsaurus Small Theropod
Early Cretaceous 12.00 Amargasaurus Sauropod
Early Jurassic 5.00 Ammosaurus Sauropod
Late Cretaceous 15.00 Ampelosaurus Sauropod
Mid Jurassic 15.00 Amygdalodon Sauropod
Late Cretaceous 6.00 Anchiceratops Ceratopsian
Early Jurassic 2.00 Anchisaurus Sauropod
Late Cretaceous 7.00 Ankylosaurus Armoured Dinosaur
Late Cretaceous 3.50 Anserimimus Large Theropod
Late Cretaceous 18.00 Antarctosaurus Sauropod
Late Jurassic 21.00 Apatosaurus Sauropod
Early Cretaceous 18.00 Aragosaurus Sauropod
Late Cretaceous 8.00 Aralosaurus Euornithopod
Early Cretaceous 1.30 Archaeoceratops Ceratopsian
Late Jurassic 0.50 Archaeopteryx Small Theropod
Late Cretaceous 3.50 Archaeornithomimus Small Theropod
Late Cretaceous 35.00 Argentinosaurus Sauropod
Late Cretaceous 6.00 Arrhinoceratops Ceratopsian
Early Cretaceous 3.00 Atlascopcosaurus Euornithopod
Late Cretaceous 5.00 Aucasaurus Large Theropod
Early Cretaceous 15.00 Austrosaurus Sauropod
Late Cretaceous 2.30 Avaceratops Ceratopsian
Late Cretaceous 1.50 Avimimus Small Theropod
Late Cretaceous 6.00 Bactrosaurus Euornithopod
Late Cretaceous 1.00 Bagaceratops Ceratopsian
Late Cretaceous 1.00 Bambiraptor Small Theropod
Early Jurassic 14.00 Barapasaurus Sauropod
Late Jurassic 24.00 Barosaurus Sauropod
Early Cretaceous 10.00 Baryonyx Large Theropod
Early Cretaceous 5.00 Becklespinax Large Theropod
Early Cretaceous 2.00 Beipiaosaurus Small Theropod
Mid Jurassic 5.00 Bellusaurus Sauropod
Late Cretaceous 1.50 Borogovia Small Theropod
Late Jurassic 30.00 Brachiosaurus Sauropod
Late Cretaceous 7.00 Brachylophosaurus Euornithopod
Mid Jurassic 10.00 Brachytrachelopan Sauropod
Late Cretaceous 1.30 Buitreraptor Small Theropod
Late Jurassic 23.00 Camarasaurus Sauropod
Late Jurassic 5.00 Camptosaurus Euornithopod
Late Cretaceous 15.00 Carcharodontosaurus Large Theropod
Late Cretaceous 7.60 Carnotaurus Large Theropod
Early Cretaceous 1.00 Caudipteryx Small Theropod
Early Cretaceous 10.00 Cedarpelta Armoured Dinosaur
Late Cretaceous 6.00 Centrosaurus Ceratopsian
Late Jurassic 6.00 Ceratosaurus Large Theropod
Mid Jurassic 15.00 Cetiosauriscus Sauropod
Mid Jurassic 18.00 Cetiosaurus Sauropod
Late Jurassic 1.10 Chaoyangsaurus Ceratopsian
Late Cretaceous 5.00 Chasmosaurus Ceratopsian
Late Triassic 4.00 Chindesaurus Small Theropod
Late Jurassic 11.00 Chinshakiangosaurus Sauropod
Late Jurassic 1.70 Chirostenotes Small Theropod
Early Cretaceous 23.00 Chubutisaurus Sauropod
Late Jurassic 4.00 Chungkingosaurus Armoured Dinosaur
Late Cretaceous 2.10 Citipati Small Theropod
Late Triassic 2.00 Coelophysis Small Theropod
Late Jurassic 1.80 Coelurus Small Theropod
Late Triassic 4.00 Coloradisaurus Sauropod
Late Jurassic 0.65 Compsognathus Small Theropod
Late Cretaceous 1.50 Conchoraptor Small Theropod
Early Cretaceous 0.25 Confuciusornis Small Theropod
Late Cretaceous 10.00 Corythosaurus Euornithopod
Early Jurassic 8.00 Cryolophosaurus Large Theropod
Late Jurassic 6.00 Dacentrurus Armoured Dinosaur
Late Cretaceous 9.00 Daspletosaurus Large Theropod
Mid Jurassic 15.00 Datousaurus Sauropod
Late Cretaceous 10.00 Deinocheirus Large Theropod
Early Cretaceous 3.00 Deinonychus Small Theropod
Late Cretaceous 8.10 Deltadromeus Large Theropod
Late Jurassic 20.00 Dicraeosaurus Sauropod
Early Jurassic 6.00 Dilophosaurus Large Theropod
Late Jurassic 26.00 Diplodocus Sauropod
Late Cretaceous 1.80 Dromaeosaurus Small Theropod
Late Cretaceous 3.50 Dromiceiomimus Large Theropod
Late Jurassic 4.00 Dryosaurus Euornithopod
Late Cretaceous 6.40 Dryptosaurus Large Theropod
Late Cretaceous 4.00 Edmontonia Armoured Dinosaur
Late Cretaceous 13.00 Edmontosaurus Euornithopod
Late Cretaceous 6.00 Einiosaurus Ceratopsian
Late Jurassic 6.20 Elaphrosaurus Large Theropod
Mid Jurassic 2.00 Emausaurus Armoured Dinosaur
Late Triassic 1.00 Eoraptor Small Theropod
Early Cretaceous 5.00 Eotyrannus Large Theropod
Early Cretaceous 15.00 Erketu Sauropod
Late Cretaceous 3.40 Erlikosaurus Small Theropod
Late Jurassic 10.00 Euhelopus Sauropod
Late Cretaceous 7.00 Euoplocephalus Armoured Dinosaur
Late Jurassic 6.20 Europasaurus Sauropod
Mid Jurassic 7.00 Eustreptospondylus Large Theropod
Early Cretaceous 4.20 Fukuiraptor Large Theropod
Early Cretaceous 4.70 Fukuisaurus Euornithopod
Late Cretaceous 6.00 Gallimimus Large Theropod
Late Jurassic 4.00 Gargoyleosaurus Armoured Dinosaur
Late Cretaceous 4.70 Garudimimus Large Theropod
Mid Jurassic 4.00 Gasosaurus Small Theropod
Late Cretaceous 0.80 Gasparinisaura Euornithopod
Early Cretaceous 4.60 Gastonia Armoured Dinosaur
Early Cretaceous 12.50 Giganotosaurus Large Theropod
Late Cretaceous 6.00 Gilmoreosaurus Euornithopod
Late Jurassic 23.00 Giraffatitan Sauropod
Early Cretaceous 5.00 Gobisaurus Armoured Dinosaur
Late Cretaceous 8.60 Gorgosaurus Large Theropod
Late Cretaceous 2.00 Goyocephale Large Theropod
Late Cretaceous 10.00 Gryposaurus Euornithopod
Late Triassic 1.80 Guaibasaurus Small Theropod
Late Jurassic 3.00 Guanlong Small Theropod
Late Cretaceous 9.00 Hadrosaurus Euornithopod
Late Jurassic 21.50 Haplocanthosaurus Sauropod
Early Cretaceous 2.00 Harpymimus Small Theropod
Late Triassic 3.00 Herrerasaurus Small Theropod
Late Jurassic 6.00 Hesperosaurus Armoured Dinosaur
Early Jurassic 1.20 Heterodontosaurus Euornithopod
Late Cretaceous 2.00 Heyuannia Small Theropod
Late Cretaceous 1.50 Homalocephale Euornithopod
Mid Jurassic 4.50 Huayangosaurus Armoured Dinosaur
Early Cretaceous 5.00 Hylaeosaurus Armoured Dinosaur
Late Cretaceous 9.00 Hypacrosaurus Euornithopod
Early Cretaceous 2.30 Hypsilophodon Euornithopod
Early Cretaceous 10.00 Iguanodon Euornithopod
Late Cretaceous 7.00 Indosuchus Large Theropod
Early Cretaceous 6.50 Irritator Large Theropod
Late Jurassic 20.00 Janenschia Sauropod
Late Cretaceous 9.00 Jaxartosaurus Euornithopod
Early Jurassic 5.00 Jingshanosaurus Sauropod
Early Cretaceous 21.00 Jobaria Sauropod
Late Jurassic 0.80 Juravenator Small Theropod
Late Jurassic 5.00 Kentrosaurus Armoured Dinosaur
Late Cretaceous 1.80 Khaan Small Theropod
Early Jurassic 9.00 Kotasaurus Sauropod
Late Cretaceous 8.00 Kritosaurus Euornithopod
Late Cretaceous 9.00 Lambeosaurus Euornithopod
Early Cretaceous 2.00 Leaellynasaura Euornithopod
Late Cretaceous 3.00 Leptoceratops Ceratopsian
Early Cretaceous 24.00 Ligabuesaurus Sauropod
Late Triassic 5.00 Liliensternus Small Theropod
Late Cretaceous 4.50 Lophorhothon Euornithopod
Early Jurassic 6.20 Lophostropheus Large Theropod
Early Jurassic 6.00 Lufengosaurus Sauropod
Early Cretaceous 9.00 Lurdusaurus Euornithopod
Late Triassic 1.20 Lycorhinus Euornithopod
Late Cretaceous 5.00 Magyarosaurus Sauropod
Late Cretaceous 9.00 Maiasaura Euornithopod
Late Cretaceous 6.00 Majungasaurus Large Theropod
Early Cretaceous 9.00 Malawisaurus Sauropod
Late Jurassic 22.00 Mamenchisaurus Sauropod
Late Cretaceous 13.00 Mapusaurus Large Theropod
Late Jurassic 6.00 Marshosaurus Large Theropod
Late Cretaceous 2.00 Masiakasaurus Small Theropod
Early Jurassic 4.00 Massospondylus Sauropod
Late Cretaceous 13.00 Maxakalisaurus Sauropod
Mid Jurassic 9.00 Megalosaurus Large Theropod
Late Triassic 12.00 Melanorosaurus Sauropod
Late Jurassic 8.20 Metriacanthosaurus Large Theropod
Late Cretaceous 0.50 Microceratus Ceratopsian
Late Cretaceous 0.60 Micropachycephalosaurus Ceratopsian
Early Cretaceous 0.80 Microraptor Small Theropod
Early Cretaceous 3.00 Minmi Armoured Dinosaur
Mid Jurassic 5.70 Monolophosaurus Large Theropod
Late Cretaceous 1.00 Mononykus Small Theropod
Late Triassic 3.00 Mussaurus Sauropod
Early Cretaceous 7.00 Muttaburrasaurus Euornithopod
Late Cretaceous 4.40 Nanshiungosaurus Large Theropod
Late Cretaceous 7.00 Nedoceratops Ceratopsian
Late Cretaceous 13.00 Nemegtosaurus Sauropod
Early Cretaceous 7.40 Neovenator Large Theropod
Late Cretaceous 10.00 Neuquenosaurus Sauropod
Early Cretaceous 15.00 Nigersaurus Sauropod
Late Cretaceous 1.00 Noasaurus Small Theropod
Early Cretaceous 5.00 Nodosaurus Armoured Dinosaur
Late Cretaceous 1.60 Nomingia Small Theropod
Late Cretaceous 5.30 Nothronychus Large Theropod
Mid Jurassic 1.00 Nqwebasaurus Small Theropod
Mid Jurassic 20.00 Omeisaurus Sauropod
Late Cretaceous 12.00 Opisthocoelicaudia Sauropod
Late Jurassic 2.00 Ornitholestes Small Theropod
Late Cretaceous 4.00 Ornithomimus Large Theropod
Late Cretaceous 2.00 Orodromeus Euornithopod
Late Cretaceous 2.10 Oryctodromeus Euornithopod
Late Jurassic 1.40 Othnielia Euornithopod
Early Cretaceous 7.00 Ouranosaurus Euornithopod
Late Cretaceous 2.00 Oviraptor Small Theropod
Late Cretaceous 8.00 Pachycephalosaurus Euornithopod
Late Cretaceous 6.00 Pachyrhinosaurus Ceratopsian
Late Cretaceous 7.00 Panoplosaurus Armoured Dinosaur
Early Jurassic 3.00 Pantydraco Euornithopod
Late Cretaceous 28.00 Paralititan Sauropod
Late Cretaceous 11.00 Parasaurolophus Euornithopod
Late Cretaceous 3.00 Parksosaurus Euornithopod
Mid Jurassic 18.00 Patagosaurus Sauropod
Early Cretaceous 2.00 Pelicanimimus Small Theropod
Early Cretaceous 25.00 Pelorosaurus Sauropod
Late Cretaceous 6.80 Pentaceratops Ceratopsian
Late Jurassic 4.20 Piatnitzkysaurus Large Theropod
Late Cretaceous 5.00 Pinacosaurus Armoured Dinosaur
Late Triassic 7.00 Plateosaurus Sauropod
Mid Jurassic 0.90 Podokesaurus Small Theropod
Mid Jurassic 9.00 Poekilopleuron Large Theropod
Early Cretaceous 5.00 Polacanthus Armoured Dinosaur
Late Cretaceous 2.40 Prenocephale Euornithopod
Early Cretaceous 6.00 Probactrosaurus Euornithopod
Mid Jurassic 4.10 Proceratosaurus Small Theropod
Late Triassic 1.00 Procompsognathus Small Theropod
Late Cretaceous 7.60 Prosaurolophus Euornithopod
Early Cretaceous 2.00 Protarchaeopteryx Small Theropod
Late Cretaceous 1.80 Protoceratops Ceratopsian
Late Cretaceous 6.00 Protohadros Euornithopod
Early Cretaceous 2.00 Psittacosaurus Ceratopsian
Late Cretaceous 23.00 Quaesitosaurus Sauropod
Early Cretaceous 20.00 Rebbachisaurus Sauropod
Late Cretaceous 4.00 Rhabdodon Euornithopod
Mid Jurassic 15.00 Rhoetosaurus Sauropod
Late Cretaceous 2.50 Rinchenia Small Theropod
Late Triassic 5.15 Riojasaurus Sauropod
Late Cretaceous 7.00 Rugops Large Theropod
Late Cretaceous 6.60 Saichania Armoured Dinosaur
Late Cretaceous 12.00 Saltasaurus Sauropod
Early Jurassic 3.00 Sarcosaurus Small Theropod
Late Cretaceous 9.00 Saurolophus Euornithopod
Early Cretaceous 6.50 Sauropelta Armoured Dinosaur
Late Jurassic 12.00 Saurophaganax Large Theropod
Late Cretaceous 3.00 Saurornithoides Small Theropod
Early Jurassic 4.00 Scelidosaurus Armoured Dinosaur
Early Jurassic 1.20 Scutellosaurus Armoured Dinosaur
Late Cretaceous 3.00 Secernosaurus Euornithopod
Mid Jurassic 1.50 Segisaurus Small Theropod
Late Cretaceous 4.00 Segnosaurus Large Theropod
Early Cretaceous 0.45 Shanag Small Theropod
Late Cretaceous 15.00 Shantungosaurus Euornithopod
Mid Jurassic 10.00 Shunosaurus Sauropod
Late Cretaceous 0.60 Shuvuuia Small Theropod
Early Cretaceous 4.00 Silvisaurus Armoured Dinosaur
Early Cretaceous 2.37 Sinocalliopteryx Small Theropod
Early Cretaceous 2.00 Sinornithosaurus Small Theropod
Early Cretaceous 1.00 Sinosauropteryx Small Theropod
Early Cretaceous 1.00 Sinovenator Small Theropod
Mid Jurassic 7.60 Sinraptor Large Theropod
Late Cretaceous 9.00 Sonidosaurus Sauropod
Late Cretaceous 18.00 Spinosaurus Large Theropod
Late Triassic 2.00 Staurikosaurus Large Theropod
Late Cretaceous 2.40 Stegoceras Euornithopod
Late Jurassic 9.00 Stegosaurus Armoured Dinosaur
Early Cretaceous 1.50 Stenopelix Ceratopsian
Late Cretaceous 4.00 Struthiomimus Small Theropod
Late Cretaceous 2.50 Struthiosaurus Armoured Dinosaur
Late Cretaceous 5.50 Styracosaurus Ceratopsian
Early Cretaceous 11.00 Suchomimus Large Theropod
Early Cretaceous 35.00 Supersaurus Sauropod
Late Cretaceous 6.00 Talarurus Armoured Dinosaur
Late Cretaceous 10.00 Tarbosaurus Large Theropod
Late Cretaceous 8.50 Tarchia Armoured Dinosaur
Late Cretaceous 5.00 Telmatosaurus Euornithopod
Early Cretaceous 7.00 Tenontosaurus Euornithopod
Late Triassic 2.50 Thecodontosaurus Sauropod
Late Cretaceous 3.50 Thescelosaurus Euornithopod
Late Cretaceous 7.50 Torosaurus Ceratopsian
Late Jurassic 10.00 Torvosaurus Large Theropod
Late Cretaceous 9.00 Triceratops Ceratopsian
Late Cretaceous 2.00 Troodon Small Theropod
Late Cretaceous 12.00 Tsintaosaurus Euornithopod
Late Jurassic 7.00 Tuojiangosaurus Armoured Dinosaur
Late Cretaceous 1.40 Tylocephale Euornithopod
Late Cretaceous 12.00 Tyrannosaurus Large Theropod
Late Cretaceous 2.40 Unenlagia Small Theropod
Late Cretaceous 1.00 Urbacodon Small Theropod
Early Cretaceous 6.00 Utahraptor Large Theropod
Early Cretaceous 3.00 Valdosaurus Euornithopod
Late Cretaceous 1.80 Velociraptor Small Theropod
Early Jurassic 6.50 Vulcanodon Sauropod
Mid Jurassic 3.00 Yandusaurus Euornithopod
Late Jurassic 10.00 Yangchuanosaurus Large Theropod
Early Jurassic 9.00 Yimenosaurus Sauropod
Mid Jurassic 1.20 Yinlong Ceratopsian
Mid Jurassic 17.00 Yuanmousaurus Sauropod
Early Jurassic 7.00 Yunnanosaurus Sauropod
Late Cretaceous 3.00 Zalmoxes Euornithopod
Early Cretaceous 1.80 Zephyrosaurus Euornithopod

Start with {ggplot2}

ggplot(data = dinosaurs) +
  aes(
    x = length, y = period,
    colour = period
  ) +
  geom_point(
    size = 4
  ) +
  scale_colour_brewer(
    palette = "Dark2",
    guide = "none"
  ) +
  labs(
    x = "Length (m)",
    y = NULL
  ) +
  theme_bw(base_size = 28)

Adding tooltips

library(ggiraph)
g <- ggplot(data = dinosaurs) +
  aes(
    x = length, y = period,
    colour = period
  ) +
  geom_point_interactive(
    mapping = aes(
      tooltip = name
    ),
    size = 4
  ) +
  scale_colour_brewer(
    palette = "Dark2",
    guide = "none"
  ) +
  labs(
    x = "Length (m)",
    y = NULL
  ) +
  theme_bw(base_size = 28)
girafe(ggobj = g)

Better tooltip labels

dinosaurs <- dinosaurs |>
  mutate(tooltips_label = glue::glue("{name}\nLength: {length}m"))


g <- ggplot(data = dinosaurs) +
  aes(x = length, y = period, colour = period) +
  geom_point_interactive(
    mapping = aes(
      tooltip = tooltips_label
    ),
    size = 4
  ) +
  scale_colour_brewer(palette = "Dark2", guide = "none") +
  labs(x = "Length (m)", y = NULL) +
  theme_bw(base_size = 28)
girafe(ggobj = g)

Better tooltip labels

Better looking tooltips

girafe(
  ggobj = g,
  options = list(
    opts_tooltip(
      css = "
      background-color:#1b9e77;
      color:white;
      padding:5px;
      border-radius:3px;",
      opacity = 1
    )
  )
)

Adding a dropdown menu

library(htmltools)
options_vec <- sort(
  unique(
    dinosaurs$type
  )
)
names(options_vec) <- options_vec

dropdown_html <- tags$div(
  tags$select(
    id = "dropdown",
    lapply(
      names(options_vec),
      function(name) {
        tags$option(
          value =
            options_vec[[name]],
          name
        )
      }
    )
  )
)

dropdown_html

Adding a dropdown menu

g <- ggplot(data = dinosaurs) +
  aes(
    x = length, y = period,
    colour = period
  ) +
  geom_point_interactive(
    mapping = aes(
      tooltip = tooltips_label,
      data_id = type
    ),
    size = 4
  ) +
  scale_colour_brewer(
    palette = "Dark2",
    guide = "none"
  ) +
  labs(
    x = "Length (m)",
    y = NULL
  ) +
  theme_bw(base_size = 28)

Adding a dropdown menu

g_girafe <- girafe(
  ggobj = g,
  options = list(
    opts_tooltip(
      css = "
      background-color:#1b9e77;
      color:white;
      padding:5px;
      border-radius:3px;",
      opacity = 1
    )
  ),
  height_svg = 4.5
)

Adding a dropdown menu

browsable(
  tagList(
    dropdown_html,
    g_girafe,
    tags$script(HTML("
      function filterByDropdown(selected) {
        document.querySelectorAll('[data-id]').forEach(el => {
          if (el.getAttribute('data-id') === selected) {
            el.setAttribute('style', 'display:block;');
          } else {
            el.setAttribute('style', 'display:none;');
          }
        });
      }

      document.getElementById('dropdown').addEventListener('change', function() {
        filterByDropdown(this.value);
      });

      // Run on initial load to filter by default selection
      document.addEventListener('DOMContentLoaded', function() {
        const initialSelected = document.getElementById('dropdown').value;
        filterByDropdown(initialSelected);
      });
    "))
  )
)

Adding a dropdown menu



Observable Plot

A JavaScript library for exploratory data visualization

What is Observable?

  • JavaScript-based reactive programming environment

  • Used for interactive data exploration, visualisation, and dashboards

  • Create and publish Observable notebooks at observablehq.com

  • Use Observable Javascript in standalone documents and websites


Observable logo

What is Observable?

Screenshot of Observable site

Why use Observable?

Especially since there are already R packages for making interactive charts!

  • Use different JavaScript libraries and CSS for advanced customisation

  • No need for a server to run code (like you do with Shiny apps)

  • Reactive and efficient rendering in a browser

  • Responsive design (screen size)

But R is still better at some things…

The best of both worlds

Data wrangling and modelling with R


Rlogo

Visualisation with Observable


Observable logo

Quarto

  • Open-source scientific and technical publishing system.

  • Combine (R/Python/Julia/Observable) code with narrative text to create reproducible outputs.

  • “Next generation R Markdown”.

  • See quarto.org.

Quarto logo

Quarto document

---
title: "My Observable and R Documnet"
execute:
  echo: false
---

```{r}

```

You can also add text to give a reader more information.

```{ojs}

```

Data wrangling in R

library(tidyverse)

# Read data
dinosaurs_raw <- read_csv("dinosaurs.csv")

# Data wrangling
dinosaurs <- dinosaurs_raw |>
  select(period, length, name, type) |>
  filter(period != "USA") |>
  mutate(
    period = str_remove(
      period, " million years ago"
    ),
    period = str_remove_all(
      period, "[0-9]"
    ),
    period = str_remove(period, "-"),
    period = str_trim(period),
    length = as.numeric(
      str_remove(length, "m")
    ),
    name = str_to_title(name),
    type = str_to_title(type)
  ) |>
  drop_na() |>
  mutate(
    period = factor(period, levels = c(
      "Late Triassic", "Early Jurassic",
      "Mid Jurassic", "Late Jurassic",
      "Early Cretaceous",
      "Late Cretaceous"
    ))
  )
period length name type
Early Jurassic 8.00 Aardonyx Sauropod
Late Cretaceous 9.00 Abelisaurus Large Theropod
Late Cretaceous 6.00 Achelousaurus Ceratopsian
Late Cretaceous 5.00 Achillobator Large Theropod
Early Cretaceous 12.00 Acrocanthosaurus Large Theropod
Late Cretaceous 15.00 Aegyptosaurus Sauropod
Early Cretaceous 9.00 Afrovenator Large Theropod
Late Jurassic 1.50 Agilisaurus Euornithopod
Late Cretaceous 21.00 Alamosaurus Sauropod
Late Cretaceous 7.00 Albertaceratops Ceratopsian
Late Cretaceous 9.00 Albertosaurus Large Theropod
Late Cretaceous 5.00 Alectrosaurus Large Theropod
Late Cretaceous 6.00 Alioramus Large Theropod
Late Jurassic 12.00 Allosaurus Large Theropod
Late Cretaceous 2.00 Alvarezsaurus Small Theropod
Early Cretaceous 12.00 Amargasaurus Sauropod
Early Jurassic 5.00 Ammosaurus Sauropod
Late Cretaceous 15.00 Ampelosaurus Sauropod
Mid Jurassic 15.00 Amygdalodon Sauropod
Late Cretaceous 6.00 Anchiceratops Ceratopsian
Early Jurassic 2.00 Anchisaurus Sauropod
Late Cretaceous 7.00 Ankylosaurus Armoured Dinosaur
Late Cretaceous 3.50 Anserimimus Large Theropod
Late Cretaceous 18.00 Antarctosaurus Sauropod
Late Jurassic 21.00 Apatosaurus Sauropod
Early Cretaceous 18.00 Aragosaurus Sauropod
Late Cretaceous 8.00 Aralosaurus Euornithopod
Early Cretaceous 1.30 Archaeoceratops Ceratopsian
Late Jurassic 0.50 Archaeopteryx Small Theropod
Late Cretaceous 3.50 Archaeornithomimus Small Theropod
Late Cretaceous 35.00 Argentinosaurus Sauropod
Late Cretaceous 6.00 Arrhinoceratops Ceratopsian
Early Cretaceous 3.00 Atlascopcosaurus Euornithopod
Late Cretaceous 5.00 Aucasaurus Large Theropod
Early Cretaceous 15.00 Austrosaurus Sauropod
Late Cretaceous 2.30 Avaceratops Ceratopsian
Late Cretaceous 1.50 Avimimus Small Theropod
Late Cretaceous 6.00 Bactrosaurus Euornithopod
Late Cretaceous 1.00 Bagaceratops Ceratopsian
Late Cretaceous 1.00 Bambiraptor Small Theropod
Early Jurassic 14.00 Barapasaurus Sauropod
Late Jurassic 24.00 Barosaurus Sauropod
Early Cretaceous 10.00 Baryonyx Large Theropod
Early Cretaceous 5.00 Becklespinax Large Theropod
Early Cretaceous 2.00 Beipiaosaurus Small Theropod
Mid Jurassic 5.00 Bellusaurus Sauropod
Late Cretaceous 1.50 Borogovia Small Theropod
Late Jurassic 30.00 Brachiosaurus Sauropod
Late Cretaceous 7.00 Brachylophosaurus Euornithopod
Mid Jurassic 10.00 Brachytrachelopan Sauropod
Late Cretaceous 1.30 Buitreraptor Small Theropod
Late Jurassic 23.00 Camarasaurus Sauropod
Late Jurassic 5.00 Camptosaurus Euornithopod
Late Cretaceous 15.00 Carcharodontosaurus Large Theropod
Late Cretaceous 7.60 Carnotaurus Large Theropod
Early Cretaceous 1.00 Caudipteryx Small Theropod
Early Cretaceous 10.00 Cedarpelta Armoured Dinosaur
Late Cretaceous 6.00 Centrosaurus Ceratopsian
Late Jurassic 6.00 Ceratosaurus Large Theropod
Mid Jurassic 15.00 Cetiosauriscus Sauropod
Mid Jurassic 18.00 Cetiosaurus Sauropod
Late Jurassic 1.10 Chaoyangsaurus Ceratopsian
Late Cretaceous 5.00 Chasmosaurus Ceratopsian
Late Triassic 4.00 Chindesaurus Small Theropod
Late Jurassic 11.00 Chinshakiangosaurus Sauropod
Late Jurassic 1.70 Chirostenotes Small Theropod
Early Cretaceous 23.00 Chubutisaurus Sauropod
Late Jurassic 4.00 Chungkingosaurus Armoured Dinosaur
Late Cretaceous 2.10 Citipati Small Theropod
Late Triassic 2.00 Coelophysis Small Theropod
Late Jurassic 1.80 Coelurus Small Theropod
Late Triassic 4.00 Coloradisaurus Sauropod
Late Jurassic 0.65 Compsognathus Small Theropod
Late Cretaceous 1.50 Conchoraptor Small Theropod
Early Cretaceous 0.25 Confuciusornis Small Theropod
Late Cretaceous 10.00 Corythosaurus Euornithopod
Early Jurassic 8.00 Cryolophosaurus Large Theropod
Late Jurassic 6.00 Dacentrurus Armoured Dinosaur
Late Cretaceous 9.00 Daspletosaurus Large Theropod
Mid Jurassic 15.00 Datousaurus Sauropod
Late Cretaceous 10.00 Deinocheirus Large Theropod
Early Cretaceous 3.00 Deinonychus Small Theropod
Late Cretaceous 8.10 Deltadromeus Large Theropod
Late Jurassic 20.00 Dicraeosaurus Sauropod
Early Jurassic 6.00 Dilophosaurus Large Theropod
Late Jurassic 26.00 Diplodocus Sauropod
Late Cretaceous 1.80 Dromaeosaurus Small Theropod
Late Cretaceous 3.50 Dromiceiomimus Large Theropod
Late Jurassic 4.00 Dryosaurus Euornithopod
Late Cretaceous 6.40 Dryptosaurus Large Theropod
Late Cretaceous 4.00 Edmontonia Armoured Dinosaur
Late Cretaceous 13.00 Edmontosaurus Euornithopod
Late Cretaceous 6.00 Einiosaurus Ceratopsian
Late Jurassic 6.20 Elaphrosaurus Large Theropod
Mid Jurassic 2.00 Emausaurus Armoured Dinosaur
Late Triassic 1.00 Eoraptor Small Theropod
Early Cretaceous 5.00 Eotyrannus Large Theropod
Early Cretaceous 15.00 Erketu Sauropod
Late Cretaceous 3.40 Erlikosaurus Small Theropod
Late Jurassic 10.00 Euhelopus Sauropod
Late Cretaceous 7.00 Euoplocephalus Armoured Dinosaur
Late Jurassic 6.20 Europasaurus Sauropod
Mid Jurassic 7.00 Eustreptospondylus Large Theropod
Early Cretaceous 4.20 Fukuiraptor Large Theropod
Early Cretaceous 4.70 Fukuisaurus Euornithopod
Late Cretaceous 6.00 Gallimimus Large Theropod
Late Jurassic 4.00 Gargoyleosaurus Armoured Dinosaur
Late Cretaceous 4.70 Garudimimus Large Theropod
Mid Jurassic 4.00 Gasosaurus Small Theropod
Late Cretaceous 0.80 Gasparinisaura Euornithopod
Early Cretaceous 4.60 Gastonia Armoured Dinosaur
Early Cretaceous 12.50 Giganotosaurus Large Theropod
Late Cretaceous 6.00 Gilmoreosaurus Euornithopod
Late Jurassic 23.00 Giraffatitan Sauropod
Early Cretaceous 5.00 Gobisaurus Armoured Dinosaur
Late Cretaceous 8.60 Gorgosaurus Large Theropod
Late Cretaceous 2.00 Goyocephale Large Theropod
Late Cretaceous 10.00 Gryposaurus Euornithopod
Late Triassic 1.80 Guaibasaurus Small Theropod
Late Jurassic 3.00 Guanlong Small Theropod
Late Cretaceous 9.00 Hadrosaurus Euornithopod
Late Jurassic 21.50 Haplocanthosaurus Sauropod
Early Cretaceous 2.00 Harpymimus Small Theropod
Late Triassic 3.00 Herrerasaurus Small Theropod
Late Jurassic 6.00 Hesperosaurus Armoured Dinosaur
Early Jurassic 1.20 Heterodontosaurus Euornithopod
Late Cretaceous 2.00 Heyuannia Small Theropod
Late Cretaceous 1.50 Homalocephale Euornithopod
Mid Jurassic 4.50 Huayangosaurus Armoured Dinosaur
Early Cretaceous 5.00 Hylaeosaurus Armoured Dinosaur
Late Cretaceous 9.00 Hypacrosaurus Euornithopod
Early Cretaceous 2.30 Hypsilophodon Euornithopod
Early Cretaceous 10.00 Iguanodon Euornithopod
Late Cretaceous 7.00 Indosuchus Large Theropod
Early Cretaceous 6.50 Irritator Large Theropod
Late Jurassic 20.00 Janenschia Sauropod
Late Cretaceous 9.00 Jaxartosaurus Euornithopod
Early Jurassic 5.00 Jingshanosaurus Sauropod
Early Cretaceous 21.00 Jobaria Sauropod
Late Jurassic 0.80 Juravenator Small Theropod
Late Jurassic 5.00 Kentrosaurus Armoured Dinosaur
Late Cretaceous 1.80 Khaan Small Theropod
Early Jurassic 9.00 Kotasaurus Sauropod
Late Cretaceous 8.00 Kritosaurus Euornithopod
Late Cretaceous 9.00 Lambeosaurus Euornithopod
Early Cretaceous 2.00 Leaellynasaura Euornithopod
Late Cretaceous 3.00 Leptoceratops Ceratopsian
Early Cretaceous 24.00 Ligabuesaurus Sauropod
Late Triassic 5.00 Liliensternus Small Theropod
Late Cretaceous 4.50 Lophorhothon Euornithopod
Early Jurassic 6.20 Lophostropheus Large Theropod
Early Jurassic 6.00 Lufengosaurus Sauropod
Early Cretaceous 9.00 Lurdusaurus Euornithopod
Late Triassic 1.20 Lycorhinus Euornithopod
Late Cretaceous 5.00 Magyarosaurus Sauropod
Late Cretaceous 9.00 Maiasaura Euornithopod
Late Cretaceous 6.00 Majungasaurus Large Theropod
Early Cretaceous 9.00 Malawisaurus Sauropod
Late Jurassic 22.00 Mamenchisaurus Sauropod
Late Cretaceous 13.00 Mapusaurus Large Theropod
Late Jurassic 6.00 Marshosaurus Large Theropod
Late Cretaceous 2.00 Masiakasaurus Small Theropod
Early Jurassic 4.00 Massospondylus Sauropod
Late Cretaceous 13.00 Maxakalisaurus Sauropod
Mid Jurassic 9.00 Megalosaurus Large Theropod
Late Triassic 12.00 Melanorosaurus Sauropod
Late Jurassic 8.20 Metriacanthosaurus Large Theropod
Late Cretaceous 0.50 Microceratus Ceratopsian
Late Cretaceous 0.60 Micropachycephalosaurus Ceratopsian
Early Cretaceous 0.80 Microraptor Small Theropod
Early Cretaceous 3.00 Minmi Armoured Dinosaur
Mid Jurassic 5.70 Monolophosaurus Large Theropod
Late Cretaceous 1.00 Mononykus Small Theropod
Late Triassic 3.00 Mussaurus Sauropod
Early Cretaceous 7.00 Muttaburrasaurus Euornithopod
Late Cretaceous 4.40 Nanshiungosaurus Large Theropod
Late Cretaceous 7.00 Nedoceratops Ceratopsian
Late Cretaceous 13.00 Nemegtosaurus Sauropod
Early Cretaceous 7.40 Neovenator Large Theropod
Late Cretaceous 10.00 Neuquenosaurus Sauropod
Early Cretaceous 15.00 Nigersaurus Sauropod
Late Cretaceous 1.00 Noasaurus Small Theropod
Early Cretaceous 5.00 Nodosaurus Armoured Dinosaur
Late Cretaceous 1.60 Nomingia Small Theropod
Late Cretaceous 5.30 Nothronychus Large Theropod
Mid Jurassic 1.00 Nqwebasaurus Small Theropod
Mid Jurassic 20.00 Omeisaurus Sauropod
Late Cretaceous 12.00 Opisthocoelicaudia Sauropod
Late Jurassic 2.00 Ornitholestes Small Theropod
Late Cretaceous 4.00 Ornithomimus Large Theropod
Late Cretaceous 2.00 Orodromeus Euornithopod
Late Cretaceous 2.10 Oryctodromeus Euornithopod
Late Jurassic 1.40 Othnielia Euornithopod
Early Cretaceous 7.00 Ouranosaurus Euornithopod
Late Cretaceous 2.00 Oviraptor Small Theropod
Late Cretaceous 8.00 Pachycephalosaurus Euornithopod
Late Cretaceous 6.00 Pachyrhinosaurus Ceratopsian
Late Cretaceous 7.00 Panoplosaurus Armoured Dinosaur
Early Jurassic 3.00 Pantydraco Euornithopod
Late Cretaceous 28.00 Paralititan Sauropod
Late Cretaceous 11.00 Parasaurolophus Euornithopod
Late Cretaceous 3.00 Parksosaurus Euornithopod
Mid Jurassic 18.00 Patagosaurus Sauropod
Early Cretaceous 2.00 Pelicanimimus Small Theropod
Early Cretaceous 25.00 Pelorosaurus Sauropod
Late Cretaceous 6.80 Pentaceratops Ceratopsian
Late Jurassic 4.20 Piatnitzkysaurus Large Theropod
Late Cretaceous 5.00 Pinacosaurus Armoured Dinosaur
Late Triassic 7.00 Plateosaurus Sauropod
Mid Jurassic 0.90 Podokesaurus Small Theropod
Mid Jurassic 9.00 Poekilopleuron Large Theropod
Early Cretaceous 5.00 Polacanthus Armoured Dinosaur
Late Cretaceous 2.40 Prenocephale Euornithopod
Early Cretaceous 6.00 Probactrosaurus Euornithopod
Mid Jurassic 4.10 Proceratosaurus Small Theropod
Late Triassic 1.00 Procompsognathus Small Theropod
Late Cretaceous 7.60 Prosaurolophus Euornithopod
Early Cretaceous 2.00 Protarchaeopteryx Small Theropod
Late Cretaceous 1.80 Protoceratops Ceratopsian
Late Cretaceous 6.00 Protohadros Euornithopod
Early Cretaceous 2.00 Psittacosaurus Ceratopsian
Late Cretaceous 23.00 Quaesitosaurus Sauropod
Early Cretaceous 20.00 Rebbachisaurus Sauropod
Late Cretaceous 4.00 Rhabdodon Euornithopod
Mid Jurassic 15.00 Rhoetosaurus Sauropod
Late Cretaceous 2.50 Rinchenia Small Theropod
Late Triassic 5.15 Riojasaurus Sauropod
Late Cretaceous 7.00 Rugops Large Theropod
Late Cretaceous 6.60 Saichania Armoured Dinosaur
Late Cretaceous 12.00 Saltasaurus Sauropod
Early Jurassic 3.00 Sarcosaurus Small Theropod
Late Cretaceous 9.00 Saurolophus Euornithopod
Early Cretaceous 6.50 Sauropelta Armoured Dinosaur
Late Jurassic 12.00 Saurophaganax Large Theropod
Late Cretaceous 3.00 Saurornithoides Small Theropod
Early Jurassic 4.00 Scelidosaurus Armoured Dinosaur
Early Jurassic 1.20 Scutellosaurus Armoured Dinosaur
Late Cretaceous 3.00 Secernosaurus Euornithopod
Mid Jurassic 1.50 Segisaurus Small Theropod
Late Cretaceous 4.00 Segnosaurus Large Theropod
Early Cretaceous 0.45 Shanag Small Theropod
Late Cretaceous 15.00 Shantungosaurus Euornithopod
Mid Jurassic 10.00 Shunosaurus Sauropod
Late Cretaceous 0.60 Shuvuuia Small Theropod
Early Cretaceous 4.00 Silvisaurus Armoured Dinosaur
Early Cretaceous 2.37 Sinocalliopteryx Small Theropod
Early Cretaceous 2.00 Sinornithosaurus Small Theropod
Early Cretaceous 1.00 Sinosauropteryx Small Theropod
Early Cretaceous 1.00 Sinovenator Small Theropod
Mid Jurassic 7.60 Sinraptor Large Theropod
Late Cretaceous 9.00 Sonidosaurus Sauropod
Late Cretaceous 18.00 Spinosaurus Large Theropod
Late Triassic 2.00 Staurikosaurus Large Theropod
Late Cretaceous 2.40 Stegoceras Euornithopod
Late Jurassic 9.00 Stegosaurus Armoured Dinosaur
Early Cretaceous 1.50 Stenopelix Ceratopsian
Late Cretaceous 4.00 Struthiomimus Small Theropod
Late Cretaceous 2.50 Struthiosaurus Armoured Dinosaur
Late Cretaceous 5.50 Styracosaurus Ceratopsian
Early Cretaceous 11.00 Suchomimus Large Theropod
Early Cretaceous 35.00 Supersaurus Sauropod
Late Cretaceous 6.00 Talarurus Armoured Dinosaur
Late Cretaceous 10.00 Tarbosaurus Large Theropod
Late Cretaceous 8.50 Tarchia Armoured Dinosaur
Late Cretaceous 5.00 Telmatosaurus Euornithopod
Early Cretaceous 7.00 Tenontosaurus Euornithopod
Late Triassic 2.50 Thecodontosaurus Sauropod
Late Cretaceous 3.50 Thescelosaurus Euornithopod
Late Cretaceous 7.50 Torosaurus Ceratopsian
Late Jurassic 10.00 Torvosaurus Large Theropod
Late Cretaceous 9.00 Triceratops Ceratopsian
Late Cretaceous 2.00 Troodon Small Theropod
Late Cretaceous 12.00 Tsintaosaurus Euornithopod
Late Jurassic 7.00 Tuojiangosaurus Armoured Dinosaur
Late Cretaceous 1.40 Tylocephale Euornithopod
Late Cretaceous 12.00 Tyrannosaurus Large Theropod
Late Cretaceous 2.40 Unenlagia Small Theropod
Late Cretaceous 1.00 Urbacodon Small Theropod
Early Cretaceous 6.00 Utahraptor Large Theropod
Early Cretaceous 3.00 Valdosaurus Euornithopod
Late Cretaceous 1.80 Velociraptor Small Theropod
Early Jurassic 6.50 Vulcanodon Sauropod
Mid Jurassic 3.00 Yandusaurus Euornithopod
Late Jurassic 10.00 Yangchuanosaurus Large Theropod
Early Jurassic 9.00 Yimenosaurus Sauropod
Mid Jurassic 1.20 Yinlong Ceratopsian
Mid Jurassic 17.00 Yuanmousaurus Sauropod
Early Jurassic 7.00 Yunnanosaurus Sauropod
Late Cretaceous 3.00 Zalmoxes Euornithopod
Early Cretaceous 1.80 Zephyrosaurus Euornithopod

Passing data from R

In R:

ojs_define(r_data = dinosaurs)


Transpose the data in Observable:

data = transpose(r_data)

Basic scatter plot

Plot.plot({
  // Draw points
  marks: [
    Plot.dot(data, {x: "length", y: "period", r: 6})
  ],
  // Sizing
  height: 750, width: 1500
})


We can add comments to document our code using // in the same way we use # in R.

Basic scatter plot

Add some styling

xDomain = d3.extent(data, d => d.length)
yDomain = ["Late Triassic", "Early Jurassic", "Mid Jurassic",
"Late Jurassic", "Early Cretaceous", "Late Cretaceous"]
// Plot
Plot.plot({
  marks: [
    Plot.dot(data, {x: "length", y: "period", fill: 'period', r: 6})
  ],
  color: {scheme: "set2"},
  // Axis labels
  x: {label: "Length (m)\n", grid: true, domain: xDomain},
  y: {label: "", domain: yDomain},
  // Sizing
  height: 750, width: 1500, marginLeft: 200, marginBottom: 90
})

Add some styling

Adding tooltips

Plot.plot({
  // Draw points
  marks: [
    Plot.dot(data, {x: "length", y: "period", fill: "period", r: 6,
    tip: true})
  ],
  color: {scheme: "set2"},
  // Axis labels
  x: {label: "Length (m)\n", grid: true, domain: xDomain},
  y: {label: "", domain: yDomain},
  // Sizing
  height: 750, width: 1500, marginLeft: 200, marginBottom: 90
})

Adding tooltips

Better tooltip labels

Plot.plot({
  // Draw points
  marks: [
    Plot.dot(data, {x: "length", y: "period", fill: "period", r: 6,
    tip: true,
    title: d => `${d.name}\nLength: ${d.length}m`})
  ],
  color: {scheme: "set2"},
  // Axis labels
  x: {label: "Length (m)\n", grid: true, domain: xDomain},
  y: {label: "", domain: yDomain},
  // Sizing
  height: 750, width: 1500, marginLeft: 200, marginBottom: 90
})

Better tooltip labels

Adding a dropdown menu

viewof types = Inputs.select(
  ["Armoured Dinosaur", "Ceratopsian", "Euornithopod",
  "Large Theropod", "Sauropod", "Small Theropod"], {
  value: "Armoured Dinosaur"
})


filtered = data.filter(function(data) {
  return types.includes(data.type);
})

Adding a dropdown menu

Plot.plot({
  marks: [
    Plot.dot(filtered, {x: "length", y: "period", fill: "period", r: 6})
  ],
  color: {scheme: "set2"},
  x: {label: "Length (m)\n", grid: true, domain: xDomain},
  y: {label: "", domain: yDomain},
  height: 700, width: 1400, marginLeft: 200, marginBottom: 90
})

Adding a dropdown menu

Final thoughts

  • Dynamic plots are usually easier to implement than truly interactive elements.
  • Sometimes writing JavaScript from the start means writing less JavaScript.
  • Use the best tool for the job.

Resources