AlgebraOfGraphics question

In Philosophy · Algebra of Graphics (
the authors explain that AlgebraOfGraphics doesn’t do mind reading and want to cut down the clutter/repetition when specifying a plot.
I wonder what is the price to pay for their approach.

Don’t get me wrong, thanks for the work! The examples are amazing and useful.
I am stumbling over the simple things.

I want to plot two lines with the same x-axis and a legend.
There is no legend command, but using the search found an example doing what I wanted:

using AlgebraOfGraphics, GLMakie

N = 40

x = [1:N; 1:N]
y = [cumsum(randn(N)); cumsum(randn(N))]
grp = [fill("a", N); fill("b", N)]

# NOT working for a single line
#x = [1:N]
#y = [cumsum(randn(N))]
#grp = [fill("a", N)]

df = (; x, y, grp)

layers = visual(Lines) + visual(Scatter) * mapping(marker = :grp)
plt = data(df) * layers * mapping(:x, :y, color = :grp)

fg = draw(plt)

From the code I understand that each y value must have its own x value and its own legend.
This looks allocation-heavy.
Additionally, the name of the legend (grp here) appears on the plot. How to suppress it?

I thought of writing a wrapper, so first experimented to cut back the example to a single plot line, without success (plots the values as single data line, no graphics).

Is there a convenience function or what am I missing?

So, I think the issue you are running into is “long vs wide vs pre-grouped data format”. In particular,

From the code I understand that each y value must have its own x value and its own legend.
This looks allocation-heavy.

seems to refer to “long form data”, which does incur in some repetition. Long-form data is in my understanding the default in e.g. ggplot2 and other Grammar of Graphics software. It definitely has its advantages but also some drawbacks.

One of the principles of AlgebraOfGraphics is that the plotting library should not enforce the data format, see this philosophy section. In particular, it seems like what you are looking for is pre-grouped data support. The exact syntax may change (see this issue), but you can already do e.g.

using AlgebraOfGraphics, GLMakie
N = 40
x = [1:N] # list of vectors for `x` axis
y = [cumsum(randn(N)), cumsum(randn(N))] # list of vectors for `y` axis
grp = ["a", "b"] # list of strings for groupings
layers = visual(Lines) + visual(Scatter) * mapping(marker = grp)
plt = layers * mapping(x, y, color = grp)
fg = draw(plt)

The different variables are combined with broadcast semantics, so x = [1:N] works the same as x = [1:N, 1:N] as it is expanded along a trailing singleton dimension.

To name axes or legends in this format you would use the pair syntax, that is x => "x", y => "y", grp => "group".


Thanks for the example, works!
The printing of the legend name grp is gone with df = (; x, y, grp) gone. Is this reasoning correct?
Now how to adapt the box surrounding the legend as well?

Honestly, I do not recognize the given code in the pre-grouped data support section.
Definitely need more study to understand the concepts behind.
How to improve accessibility? Simple examples help for sure.
Thx again.

Yes, AoG tries to infer the name, but if you pass the variable directly, it is unnamed by default (there is no way to know the name of the variable from the function).

I’m not sure there is an easy way at the moment (AoG simply removes the box altogether in its default style, so that may help). It would probably be a good “getting started” PR to set up the legend creation so that it calls the “title-free” MakieLayout legend method when the legend title is the empty string.

How to apply the pair syntax?
I tried some possible places.
VSCode flags where the syntax is obviously wrong, other locations give run-time errors.
I searched but could not find code with => in the tutorial or gallery examples.