Working with @with, Dataframes and Makie

I am still trying to figure out best ways of interactive plotting of DataFrames in GLMakie… AlgebraofGraphics is nice, but some things can become a bit complicated (cf. Interactive Menu with AlgebraOfGraphics / GLMakie - #12 by lazarusA)

So I was thinking of the @with macro from StaticModules

using StaticModules, GLMakie, DataFrames
x1=rand(50)
y1=10x1.^2
y2=x1 .+ randn(50)
df = DataFrame((;x1, y1, y2))

var=Observable("y1")

fig = @with df begin
    fig=Figure(); ax = Axis(fig[1,1])
    scatter!(ax, x1, @lift(df[!,$var]), color=y2.-y1)
    on(var) do i
        autolimits!(ax)
   end
   fig
end
 
var[]="y2"

It works, but repeating the df in the @lift is a bit annoying and I am wondering if this is viable way to go (new to Julia…)
Thanks!

I would do a Menu, and put all things lift related before calling the plot (if possible), as in:

using GLMakie, DataFrames
x1=rand(50)
y1=10x1.^2
y2=x1 .+ randn(50)
df = DataFrame((;x1, y1, y2))

var=Observable("y1")
yv = @lift(df[!,$var])

fig=Figure()
ax = Axis(fig[1,1])
menu = Menu(fig, options = ["y1", "y2"])
scatter!(ax, x1, yv; color = y2.-y1)

fig[1,0] = vgrid!(Label(fig, "Variable", width = nothing), menu;
    tellheight = false, width = 150)
on(menu.selection) do s
    var[] = s
    autolimits!(ax)
end
menu.is_open = true
fig

Note: In your previous approach inside the @with block you are actually creating a new figure each time, and not just updating the previous figure, hence it will lead to bad performance.

Thanks for the reply - so do you advise against using @with at all? Imagine a case where the df is coming from “somewhere else”, e.g. a file - then x1 etc. would not available as variable and one would have to write first

(; x1, y1, y2) = df

and then repeat the varnames also in the scatter call.

Sure, but that’s a different story…

Are you sure? @macroexpand shows nothing in this direction - mostly just the df. is added where appropriate.

Imagine a case where the df is coming from “somewhere else”

Then I would do the data processing step first and then plot. I’m more in favour of the idea data comes first.
Mixing analysis and plotting in the same workflow is prone to errors, at least for me :smile: . This is a personal preference.

Are you sure?

@with df begin
    fig=Figure()

only if this is trigger every time there is a new update, not really sure if is activated here :laughing: , either way I would do the

fig=Figure(); ax = Axis(fig[1,1])

before, just to be sure, plus I think it will be cleaner.

1 Like