Skip to contents

orbis describes a plot with a layered grammar, then compiles that description to a scene of drawing primitives. Because the scene is resolution independent, the same plot object can become an interactive figure in a browser or a 600 dpi image for a journal, with nothing re-specified.

The grammar

A plot starts with data and a mapping from variables to visual channels. Layers are added with +.

p <- orb(mtcars, x = wt, y = mpg, colour = hp, size = disp) +
  orb_points() +
  orb_labs(title = "Fuel economy", x = "Weight (1000 lbs)",
           y = "Miles per gallon", colour = "Horsepower")
p
10152025301.522.533.544.555.5Fuel economyWeight (1000 lbs)Miles per gallonHorsepower33552

Recognised channels are x, y, colour (or color), fill, size, label, group and tooltip. A mapping given inside a layer applies to that layer only.

Continuous variables mapped to colour use a perceptually uniform ramp; character or factor variables get a qualitative palette and an interactive legend.

orb(mtcars, x = wt, y = mpg, colour = factor(cyl)) +
  orb_points() +
  orb_theme_dark()
10152025301.522.533.544.555.5factor(cyl)468

Layers

set.seed(1)
df <- data.frame(t = 1:80, v = cumsum(rnorm(80, 0.05)))

orb(df, x = t, y = v) +
  orb_area(alpha = 0.3) +
  orb_line(width = 2, smooth = TRUE) +
  orb_labs(title = "A smoothed series")
05101501020304050607080A smoothed series

orb_bars() accepts a discrete x:

counts <- data.frame(g = c("alpha", "beta", "gamma", "delta"),
                     v = c(23, 41, 17, 35))
orb(counts, x = g, y = v, fill = g) +
  orb_bars() +
  orb_options(legend = FALSE, grid = "y") +
  orb_theme_ink()
010203040alphabetadeltagamma

Small multiples

orb_facet() draws one panel per level of a variable. Panels share their scales by default, which is what makes them comparable at a glance.

orb(mtcars, x = wt, y = mpg, colour = hp) +
  orb_points() +
  orb_facet(cyl) +
  orb_labs(title = "By cylinder count", x = "Weight", y = "MPG")
1015202530423456101520253023458By cylinder countWeightMPGhp33552

Use scales = "free" (or "free_x", "free_y") when panels cover very different ranges, and ncol to control the grid:

set.seed(3)
d <- data.frame(t = rep(1:40, 3),
                v = c(cumsum(rnorm(40)), cumsum(rnorm(40, 0.3)),
                      cumsum(rnorm(40, -0.2))),
                region = rep(c("north", "south", "east"), each = 40))
orb(d, x = t, y = v) +
  orb_area(alpha = 0.3) + orb_line() +
  orb_facet(region, ncol = 3, scales = "free_y")
-4-202010203040east-8-6-4-20010203040north0510010203040south

Colours and sizes are resolved across the whole data set rather than per panel, so a colour means the same thing everywhere.

Scales

Scales set palettes, limits and axis transformations.

orb(mtcars, x = wt, y = mpg, colour = hp) +
  orb_points() +
  orb_scale_colour("magma", reverse = TRUE) +
  orb_scale_size(range = c(3, 16)) +
  orb_scale_y(limits = c(10, 35))
1015202530351.522.533.544.555.5hp33552

Available palettes:

orb_palettes()
#> $continuous
#> [1] "viridis"  "magma"    "mako"     "ember"    "ice"      "spectral" "balance" 
#> 
#> $discrete
#> [1] "orbis" "vivid" "earth" "neon"

Maps

A simplified world dataset ships with the package.

str(world_map)
#> 'data.frame':    26953 obs. of  4 variables:
#>  $ long  : num  -69.9 -70.1 -70 -69.9 74.9 ...
#>  $ lat   : num  12.5 12.5 12.6 12.5 37.2 ...
#>  $ group : int  1 1 1 1 2 2 2 2 2 2 ...
#>  $ region: chr  "Aruba" "Aruba" "Aruba" "Aruba" ...

orb_worldmap() is the quickest way to a map. Supply values to shade regions by a variable.

vals <- data.frame(region = c("Brazil", "India", "France", "China", "Nigeria"),
                   v = c(3, 9, 5, 8, 6))
orb_worldmap(values = vals, value_col = "v", projection = "robinson") +
  orb_labs(title = "A small choropleth")
A small choroplethv93

Six projections are built in. equalearth is a good modern default for thematic maps: it is equal-area, so shaded country sizes are directly comparable, while keeping continents close to their familiar shapes.

orb_worldmap(values = vals, value_col = "v", projection = "equalearth",
             palette = "ice") +
  orb_labs(title = "Equal Earth")
Equal Earthv93

The orthographic projection draws a globe and hides the hemisphere facing away from the viewer.

orb_worldmap(projection = "orthographic", ocean = "#0B1F33") +
  orb_coord_map("orthographic", centre = c(20, 15)) +
  orb_theme_dark()

Points are placed on the active projection with orb_geo_points():

cities <- data.frame(
  long = c(2.35, -74.0, 151.2, 77.2, -43.2),
  lat  = c(48.86, 40.7, -33.87, 28.6, -22.9),
  pop  = c(11, 19, 5, 32, 13)
)
orb(cities, x = long, y = lat, size = pop) +
  orb_map(fill = "#E9ECEF") +
  orb_geo_points(colour = "#F76707") +
  orb_coord_map("robinson") +
  orb_labs(title = "Cities")
Citiespop532

Output

One plot object, several destinations. The format follows the file extension.

orb_save(p, "figure.png", dpi = 600)   # high-resolution raster for print
orb_save(p, "figure.pdf")              # vector
orb_save(p, "figure.svg")              # vector, still interactive
orb_save(p, "figure.html")             # self-contained interactive page
orb_interactive(p)                     # open in the viewer

Raster output is laid out at width x height logical pixels and then rendered at the requested dpi, so a 300 or 600 dpi figure keeps the same proportions as what you saw on screen.

The interactive output supports:

  • hovering a mark for a tooltip,
  • scrolling to zoom and dragging to pan,
  • double-clicking to reset the view,
  • clicking a legend key to hide or show that series.

Set orb_options(interactive = FALSE) if a document must not contain scripts.

What orbis does not do yet

There are no statistical layers, so summarise data before plotting: there is no smoother, boxplot or histogram geometry yet. Text is measured approximately when laying out axes and legends, because the SVG writer does not query a font engine, so very long labels can be spaced imperfectly. The bundled world map is simplified for figure-sized output rather than for detailed cartography.