Grammar of Graphics with AlgebraOfGraphics.jl

Authors

Jose Storopoli

Juan Oneto

This tutorial will be a deep dive into AoG.jl grammar and algebraic operations. All revolves around the AlgebraOfGraphics.Layer and AlgebraOfGraphics.Layers types. They represent a single layer or a list of layers, respectively. These are the types you can add and multiply in AoG.jl with + and *.

Each layer in AoG.jl is composed of data, mappings and transformations.

Tip

Even if you do not specify a transformation with visual(), AoG.j will default to visual(Scatter). So every layer has always these three components.

You can replace data, merge mappings or concatenate transformations. All these operations are defined in a multiplication operation with *.

The addition operation + is used to superimpose separated layers.

In summary:

To begin, like before, let’s load AoG.jl, data wrangling libraries and the DataFrame we’ve used previously:

using PharmaDatasets
using DataFramesMeta

df = dataset("demographics_1")
first(df, 5)
5×6 DataFrame
Row ID AGE WEIGHT SCR ISMALE eGFR
Int64 Float64 Float64 Float64 Int64 Float64
1 1 34.823 38.212 1.1129 0 42.635
2 2 32.765 74.838 0.8846 1 126.0
3 3 35.974 37.303 1.1004 1 48.981
4 4 38.206 32.969 1.1972 1 38.934
5 5 33.559 47.139 1.5924 0 37.198
using CairoMakie
using AlgebraOfGraphics

Now let’s create three layers:

  1. a data() layer with a data structure, e.g., a DataFrame.
  2. a mapping() layer with the columns :AGE and :eGFR called cols.
  3. a transformation visual() layer with the Scatter plotting type as geom.
df_layer = data(df)
cols = mapping(:AGE, :eGFR)
geom = visual(Scatter)

1 ✖️ Multiplication of Layers with the * Operator

To show how we can merge layers with the * operator, see the following example. Here we are combining the information from the data() layer, the mapping() layer (with the cols) and the transformation visual() layer (with the geom) into a single layer.

You can see that the returned object of the operations with the * is a AlgebraOfGraphics.Layer:

new_layer = df_layer * cols * geom;
typeof(new_layer)
Layer

And here is the new_layer visualization:

new_layer |> draw

2 ➕ Addition of Layers with the + Operator

The addition operator + does not combine AoG.jl’s Layers objects into a single Layer object like the *. Instead it returns a AlgebraOfGraphics.Layers object (note the s in Layers) which is a list of Layers:

separate_layers = visual(Scatter) + linear();
typeof(separate_layers)
Layers

And this is the visualization of the superimposition of Layers with the + operator:

data(df) * cols * separate_layers |> draw

If we want to combine the linear() layer with another, we can do so with the * operator:

data(df) * cols * (visual(Scatter) + linear() * visual(; linewidth = 3, color = :red)) |>
draw

3 🧮 Mixing + and *

Layers can be combined with pairwise products with:

combined_layer1 * combined_layer2

This will create all pairwise combinations of the combined_layer1 with combined_layer2. See this example with a data_layer, a scatter_layer and a linear_layer:

data_layer = data(df) * mapping(:AGE, :eGFR);
scatter_layer = visual(Scatter);
linear_layer = linear() * visual(; linewidth = 3);
data_layer * (scatter_layer + linear_layer) |> draw

4 🪧 Conclusion

Just remember that:

  • * combines layer into an AlgebraOfGraphics.Layer.
  • + superimposes layers into a list of layers: a AlgebraOfGraphics.Layers.
  • Be aware that you might need to use parentheses () to specify the order and scope of * and + operations.