[ANN] AlgebraOfGraphics v0.7

Hello everybody,

I’m excited to present version 0.7 of AlgebraOfGraphics.jl. This is work that I’ve been doing during the last two or three months, as we at PumasAI like to use the package but it had been in need of some refactoring for a while. This refactor is breaking in some aspects but it leaves the basic ideas and framework of the package untouched, so a transition is hopefully straightforward. It mostly adds some semantics on top that make it more flexible and powerful.

For more information about the reasoning behind all of this, please refer to PR 505. For a brief overview of the breaking changes and new features, check Release Notes · Algebra of Graphics. Note that because there are so many of them, not all of Makie’s plotting functions or all plot attributes have been enabled for the new system, yet, if you need a specific one please open an issue or file a PR.

Here are some example plots showcasing the new capabilities because we all like images to look at :slight_smile: Hope you enjoy the new release!

Horizontal/vertical bar plots, rainclouds, violins, errorbars, etc.

df = (; x = 1:10, y = string.('A':'J'))
data(df) * mapping(:y, :x) * visual(BarPlot, direction = :x) |> draw

group = repeat(["A", "B", "C", "D"], inner = 250)
measurements = randn(1000) .* repeat(1:4, inner = 250)
df = (; group, measurements)
data(df) * mapping(:group, :measurements, color = :group) *
    visual(RainClouds, orientation = :horizontal) |> draw

mapping with raw vectors, not using data():

mapping(1:90, cumsum(randn(90)), color = repeat(["A", "B", "C"], inner = 30)) *
    visual(Scatter) |> draw

Quickly use data from outside a tabular dataset with direct

df = (; x = 1:20, group = repeat(["A", "B"], inner = 10))
y = sin.(range(0, 2pi, length = 20))
data(df) * mapping(:x, direct(y), color = :group) |> draw

Markersize mapping with legend

t = 0:0.1:10
mapping(cos.(t) .* t, sin.(t) .* t, markersize = t) * visual(Scatter) |> draw

Separate scales of same aesthetic type

spec1 = mapping(
    1:300,
    cumsum(randn(300)) .+ repeat([0, 10, 20], inner = 100),
    color = repeat(["A", "B", "C"], inner = 100)
) * visual(Scatter)

spec2 = mapping([30, 80, 178, 260], color = ["X", "Y", "X", "Y"] => scale(:secondary)) *
    visual(VLines, linestyle = :dash, linewidth = 2)
    
draw(spec1 + spec2, scales(secondary = (; palette = [:tomato, :gray60])))

Category additions and modified placement

df = (; x = ["A", "C", "D", "missing"], y = [3, 2, 6, 3])
data(df) * mapping(:x, :y) * visual(BarPlot) |>
    draw(
        scales(
            X = (;
                categories = ["A", "B", "C", "D", "missing"],
                palette = [1, 2, 3, 4, 6]
        )
    )
)

Map strokecolor and other color attributes not named color

mapping(randn(50), randn(50), strokecolor = rand(["A", "B"], 50)) * 
    visual(Scatter, color = :gray90, strokewidth = 3, markersize = 20) |> draw

Reorder legends

df = (;
    x = 1:12,
    y = 1:12,
    z = 1:12,
    group1 = repeat(["A", "B", "C"], inner = 4),
    group2 = repeat(["X", "Y"], 6),
)

spec = data(df) *
    mapping(:x, :y, markersize = :z, color = :group1, marker = :group2) *
    visual(Scatter)

draw(spec; legend = (; order = [:MarkerSize, :Color, :Marker]))

Merge legends

df = (;
    x = 1:12,
    y = 1:12,
    z = 1:12,
    group1 = repeat(["A", "B", "C"], inner = 4),
    group2 = repeat(["X", "Y"], 6),
)

spec = data(df) *
    mapping(:x, :y, markersize = :z, color = :group1, marker = :group2) *
    visual(Scatter)

draw(spec; legend = (; order = [[:MarkerSize, :Color, :Marker] => "Merged"]))

53 Likes

This is awesome. Thanks for the work :heart:

1 Like