diff --git a/README.md b/README.md index 16113a1..bb05a25 100644 --- a/README.md +++ b/README.md @@ -90,12 +90,22 @@ The goal of this package is to allow you to write code that is as similar to ggp If you use Option 1, you get experimental support for calculations inside aes, including `+`, `-`, `*`, `/` and function application. Functions can be applied to columns with the `>>` operator, or wrapped for aes use with the `aesthetics_function()` command. The following geom_point specifications are equivalent: ``` -my_func(x) = x ./ 10 -my_aes_func = aesthetics_function(my_func) +my_fn(x) = x ./ 10 +my_aes_fn = aesthetics_function(my_fn) geom_point(aes(x = :x/10)) -geom_point(aes(x = :x >> my_func)) -geom_point(aes(x = my_aes_func(:x))) +geom_point(aes(x = :x >> my_fn)) +geom_point(aes(x = my_aes_fn(:x))) +``` + +Functions can take multiple columns as input (up to two, currently). The following `geom_point` specifications are equivalent, and result in `x / y` being plotted as the x axis of the graph: + +``` +my_new_fn(x, y) = x ./ y +my_new_aes_fn = aesthetics_function(my_new_fn) + +geom_point(aes(x = :x/:y)) +geom_point(aes(x = my_aes_fn(:x, :y))) ``` ## Why would I use this instead of ggplot2? diff --git a/src/transforms.jl b/src/transforms.jl index e7f21ea..79d9340 100644 --- a/src/transforms.jl +++ b/src/transforms.jl @@ -31,6 +31,9 @@ end (at::AesTransform)(sym::Symbol) = [sym] => at (at::AesTransform)(str::String) = [Symbol(str)] => at +(at::AesTransform)(s1::Symbol, s2::Symbol) = [s1, s2] => at +(at::AesTransform)(s1::String, s2::String) = [Symbol(s1), Symbol(s2)] => at + # simplest one is as_is, which just gets a column # exactly as it is in the DataFrame @@ -152,10 +155,12 @@ discard = AesTransform(discard_fn) function aesthetics_function(generic_fn::Function) function aes_fn(target::Symbol, source::Vector{Symbol}, data::DataFrame) + result = generic_fn([data[!, s] for s in source]...) + return Dict{Symbol, PlottableData}( target => PlottableData( - data[!, source[1]], # get the column out of the dataframe - generic_fn, # apply generic_fn to it + result, # put the result in raw + identity, # do nothing nothing, nothing ) diff --git a/test/test_aes_ops.jl b/test/test_aes_ops.jl index 24d19a8..9086f4b 100644 --- a/test/test_aes_ops.jl +++ b/test/test_aes_ops.jl @@ -152,7 +152,7 @@ @test plot_images_equal(t, m) end - @testset "apply function" begin + @testset "one col function" begin my_func(x) = x ./ 10 my_aes_func = aesthetics_function(my_func) @@ -193,4 +193,27 @@ @test plot_images_equal(t, m) end + @testset "two col function" begin + my_func(x, y) = x ./ y + my_aes_func = aesthetics_function(my_func) + + t = ggplot(penguins) + + geom_point(aes(x = my_aes_func(:bill_length_mm, :bill_depth_mm), y = :bill_depth_mm)) + + m = Makie.plot( + Makie.SpecApi.GridLayout( + Makie.SpecApi.Axis( + plots = [ + Makie.PlotSpec( + :Scatter, + penguins.bill_length_mm ./ penguins.bill_depth_mm, + penguins.bill_depth_mm) + ] + ) + ) + ) + + @test plot_images_equal(t, m) + end + end \ No newline at end of file