The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Extracting Plot Specifications with ggspec

Introduction

ggspec provides a family of spec_*() functions that inspect a ggplot2 object and return its declarative specification as tidy data frames. This makes it easy to answer questions like:

library(ggspec)
library(ggplot2)

A motivating example

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(colour = class)) +
  geom_smooth(method = "lm", se = FALSE) +
  facet_wrap(~drv) +
  scale_colour_brewer(palette = "Set1") +
  labs(title = "Engine displacement vs highway MPG",
       x     = "Displacement (L)",
       y     = "Highway MPG (hwy)")
p
#> `geom_smooth()` using formula = 'y ~ x'

Layer specification

spec_layers() returns one row per layer, with columns for the geom, stat, position adjustment, and resolved aesthetic mappings.

spec_layers(p)
#> # A tibble: 3 × 8
#>   layer geom   stat     position mapping   params           inherit_aes data_id
#>   <int> <chr>  <chr>    <chr>    <list>    <list>           <lgl>         <int>
#> 1     0 <NA>   <NA>     <NA>     <chr [2]> <list [0]>       NA                1
#> 2     1 point  identity identity <chr [3]> <named list [2]> TRUE             NA
#> 3     2 smooth smooth   identity <chr [2]> <named list [7]> TRUE             NA

The mapping column is a list-column of named character vectors, where each name is an aesthetic and each value is the variable mapped to it.

# Inspect the mapping for layer 1 (geom_point)
spec_layers(p)$mapping[[1]]
#>       x       y 
#> "displ"   "hwy"

Controlling inheritance

By default (inherit = "resolve"), global mappings set in ggplot() are merged with layer-local mappings, with the local mapping taking precedence for any aesthetic defined in both.

# inherit = FALSE: only mappings explicitly set on the layer
spec_layers(p, inherit = FALSE)$mapping
#> [[1]]
#>       x       y 
#> "displ"   "hwy" 
#> 
#> [[2]]
#>  colour 
#> "class" 
#> 
#> [[3]]
#> named character(0)

Aesthetic specification (long format)

spec_aes() pivots the mapping information into long format — one row per (layer-aesthetic) pair — making it easy to filter and inspect with standard dplyr operations.

spec_aes(p)
#> # A tibble: 7 × 5
#>   layer geom   aesthetic variable source
#>   <int> <chr>  <chr>     <chr>    <chr> 
#> 1     0 <NA>   x         displ    global
#> 2     0 <NA>   y         hwy      global
#> 3     1 point  x         displ    global
#> 4     1 point  y         hwy      global
#> 5     1 point  colour    class    local 
#> 6     2 smooth x         displ    global
#> 7     2 smooth y         hwy      global

The source column distinguishes:

library(dplyr)
spec_aes(p) |>
  filter(aesthetic == "colour")
#> # A tibble: 1 × 5
#>   layer geom  aesthetic variable source
#>   <int> <chr> <chr>     <chr>    <chr> 
#> 1     1 point colour    class    local

Scale specification

spec_scales() lists only explicitly added scales (default scales inferred at render time are not included, as they do not exist in the object before rendering).

spec_scales(p)
#> # A tibble: 1 × 6
#>   aesthetic scale_class   scale_type name  transform guide 
#>   <chr>     <chr>         <chr>      <chr> <chr>     <chr> 
#> 1 colour    ScaleDiscrete discrete   <NA>  <NA>      legend

Facet specification

spec_facets() returns a single-row data frame describing the faceting.

spec_facets(p)
#> # A tibble: 1 × 6
#>   facet_type rows  cols  scales space labeller       
#>   <chr>      <chr> <chr> <chr>  <chr> <chr>          
#> 1 wrap       <NA>  drv   fixed  <NA>  params$labeller

For an unfaceted plot, facet_type is "null".

Label specification

spec_labels(p)
#> # A tibble: 3 × 2
#>   aesthetic label                             
#>   <chr>     <chr>                             
#> 1 x         Displacement (L)                  
#> 2 y         Highway MPG (hwy)                 
#> 3 title     Engine displacement vs highway MPG

Coordinate system specification

spec_coord(p)
#> # A tibble: 1 × 5
#>   coord_type xlim   ylim   expand clip 
#>   <chr>      <list> <list> <lgl>  <chr>
#> 1 cartesian  <NULL> <NULL> TRUE   on

# Flipped coordinates
spec_coord(p + coord_flip())
#> # A tibble: 1 × 5
#>   coord_type xlim   ylim   expand clip 
#>   <chr>      <list> <list> <lgl>  <chr>
#> 1 flip       <NULL> <NULL> TRUE   on

The master summary: spec_plot()

spec_plot() joins all of the above into a single wide data frame with one row per layer. Scale, facet, coordinate, and label information are embedded as list-columns, so all plot information is reachable from a single object.

sp <- spec_plot(p)
sp
#> # A tibble: 3 × 14
#>   layer geom   stat   position mapping params       inherit_aes data_id aes_long
#>   <int> <chr>  <chr>  <chr>    <list>  <list>       <lgl>         <int> <list>  
#> 1     0 <NA>   <NA>   <NA>     <chr>   <list [0]>   NA                1 <tibble>
#> 2     1 point  ident… identity <chr>   <named list> TRUE             NA <tibble>
#> 3     2 smooth smooth identity <chr>   <named list> TRUE             NA <tibble>
#> # ℹ 5 more variables: datasets <list>, scales <list>, facets <list>,
#> #   coord <list>, labels <list>

# Access per-layer aesthetics
sp$aes_long[[1]]
#> # A tibble: 2 × 5
#>   layer geom  aesthetic variable source
#>   <int> <chr> <chr>     <chr>    <chr> 
#> 1     0 <NA>  x         displ    global
#> 2     0 <NA>  y         hwy      global

# Access the facet spec (same in every row)
sp$facets[[1]]
#> # A tibble: 1 × 6
#>   facet_type rows  cols  scales space labeller       
#>   <chr>      <chr> <chr> <chr>  <chr> <chr>          
#> 1 wrap       <NA>  drv   fixed  <NA>  params$labeller

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.