GiovineItalia / Gadfly.jl

Crafty statistical graphics for Julia.
http://gadflyjl.org/stable/
Other
1.9k stars 250 forks source link

Generally allow functions to fall through to evalmapping #1474

Open CiaranOMara opened 4 years ago

CiaranOMara commented 4 years ago

When I set up a plot in Gadfly, I typically need to map data from a struct, I found that I can extend Gadfly.evalmaping to avoid writing wrappers.

using Gadfly
using KernelDensity

# Provide Gadfly with the functions to handle UnivariateKDE as a data source.
Gadfly.evalmapping(source::UnivariateKDE, arg::Function) = arg(source)
Gadfly.evalmapping(source::UnivariateKDE, arg::Symbol) = getproperty(source, arg)

data = rand(100)

plot(
    kde(data),
    x = (s)->collect(s.x),
    y = :density,
    Geom.line,
)

However, not all geometries can handle mappings of functions.

function maximum_density(d::UnivariateKDE)
    (max, i) = findmax(d.density)
    return d.x[i]
end

plot(
    kde(data),
    x = (source)->collect(source.x),
    y = :density,
    xintercept = maximum_density, # <- this is what I'd like to be able to do
    # xintercept = [maximum_density(kde(data))],
    Geom.line,
    Geom.vline
)

While I know that in this case, it is trivial to evaluate kde(data) in an outside scope, its result is not always something that I'd want to keep in that scope.

Mattriks commented 3 years ago

I can make the above example work like so:

using Gadfly, Gadfly.Stat.KernelDensity

Gadfly.evalmapping(source::UnivariateKDE, arg::Function) = arg(source)
Gadfly.evalmapping(source::UnivariateKDE, arg::Symbol) = getfield(source, arg)

maximum_density(d::UnivariateKDE) = [d.x[argmax(d.density)]]

data = randn(100)

plot(kde(data), x=:x, y=:density, Geom.line, xintercept=maximum_density, Geom.vline(color="blue"))

At the moment I think the two evalmapping functions here are a bit specific for Gadfly, but I welcome other people's input. It would be good to put an example of this in the Gadly docs (perhaps in a section Advanced Gadfly - Plotting custom types).

bjarthur commented 3 years ago

let's definitely document this. that's pretty cool!