Skip to content

Commit

Permalink
2 column function support
Browse files Browse the repository at this point in the history
  • Loading branch information
rdboyes committed Apr 8, 2024
1 parent 83e1276 commit 0f36e38
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 7 deletions.
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
9 changes: 7 additions & 2 deletions src/transforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
)
Expand Down
25 changes: 24 additions & 1 deletion test/test_aes_ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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

0 comments on commit 0f36e38

Please sign in to comment.