## 5.8 A Makie recipe for a DataFrame

Unlike other libraries that already support a wide set of input formats via recipes, i.e. Plots.jl, in Makie.jl most of the time we need to pass the raw data to functions. However, we can also define our own recipe in Makie.jl. A recipe is your own custom plotting type command. This extension is done just in Makie.jl, which means that making a new set of plotting rules for your own types is light, namely, you don’t need the complete plotting machinery available to define them. This is specially useful if you want to include your own plotting commands in one of your own packages. However, in order for them to work you will still need to use one of the backends, i.e., GLMakie or CairoMakie.

As an example we will code a small full recipe for a DataFrame. Please refer to the documentation for more details.

A Makie recipe consist of two parts, a plot type name defined via @recipe and a custom plot!(::Makie.plot) which creates the actual plot via plotting functions already defined.

@recipe(DfPlot, df) do scene
Attributes(
x = :A,
y = :B,
c = :C,
color = :red,
colormap = :plasma,
markersize = 20,
marker = :rect,
colorrange = (0,1),
label = "",
)
end

Note that the macro @recipe will automatically create two new functions for us, dfplot and dfplot!, all lowercase from our type DfPlot. The first one will create a complete new figure whereas the second one will plot into the current axis or an axis of your choosing. This allows us to plot DataFrames which contains columns named, x, y, z. Now, let’s take care of our plot definition. We will do a simple scatter plot:

import Makie
function Makie.plot!(p::DfPlot{<:Tuple{<:DataFrame}})
df = p[:df][]
x = getproperty(df, p[:x][])
y = getproperty(df, p[:y][])
c = getproperty(df, p[:c][])
scatter!(p, x, y; color = c, markersize = p[:markersize][],
colormap = p[:colormap][], marker = p[:marker][],
colorrange = (minimum(x), maximum(c)), label = p[:label][])
return p
end

Note the extras [] at the end of each variable. Those are due to the fact that recipes in Makie are dynamic, meaning that our plots will update if our variables change. See observables to know more. Now, we apply our new plotting function to the following DataFrame:

df_recipe = DataFrame(A=randn(10), B=randn(10), C=rand(10))
fig, ax, obj = dfplot(df_recipe; label = "test")
axislegend()
Colorbar(fig[1,2], obj)
fig

The named attributes in the recipe allows us to pass custom names to our new plotting function. Namely:

df_names = DataFrame(a1=rand(100), a2=rand(100), a3=rand(100))

and:

dfplot(df_names; x = :a1, y = :a2, c = :a3, marker = 'o',
axis = (; aspect=1, xlabel = "a1", ylabel = "a2"),
figure = (; backgroundcolor = :grey90))

Note, that now we are calling by name each column as well as the marker type, allowing us to use this definition for different DataFrames. Additionally, all our previous options, i.e., axis or figure also work!

CC BY-NC-SA 4.0 Jose Storopoli, Rik Huijzer, Lazaro Alonso