Why this StatsPlots code does not work with constructed symbols?

Viewed 27

This code works and produces a nice chart:

using DataFrames, StatsPlots

df = DataFrame(A = rand(20), C = repeat([1,2,3, 4], inner = 5))

plt_dens1 = @df df density(
    :A,
    group = :C,
    title = "This works"
)

If the Symbol arguments are constructed as below, code that is similar does not work.

asymb = Symbol("A")
csymb = Symbol("C")

plt_dens2 = @df df density(
    asymb,
    group = csymb,
    title = "This doesn't work"
)

It generates an error message starting with:

"ERROR: MethodError: no method matching _extract_group_attributes(::Symbol, ::Symbol)" is generated."

The code below generates a chart just like the first one above:

plt_dens3 = @df df density(
    df[:, Symbol("A")],
    group = df[:, Symbol("C")],
    title = "This also works"
)

However, it is a little more cumbersome.

Question: Why doesn’t the code for plt_dens2 work and is there a simple way to fix the problem?

1 Answers

The reason is that @df macro is designed for simple use cases when column names are passed as literals.

Instead of @df use @with from DataFramesMeta.jl and all will work as expected:

using DataFramesMeta
@with df density(              
    $asymb,                    
    group = $csymb,            
    title = "This doesn't work"
)                              

Note that you need to prefix variable names with $ to interpolate their values, see https://juliadata.github.io/DataFramesMeta.jl/stable/#dollar for more explanations.

Related