AlgebraOfGraphics.jl icon indicating copy to clipboard operation
AlgebraOfGraphics.jl copied to clipboard

Simpler syntax for data+mapping

Open knuesel opened this issue 4 years ago • 2 comments

This is to discuss a simpler syntax for passing data and mappings together, as requested on Discourse.

The given example was

x = range(-π, π, length=100)
y = sin.(x)

df = (; x, y)
data(df) * mapping(:x, :y) * visual(Lines)

In Gadfly the last two lines are simply layer(x = x, y = y, Geom.line).

It's actually not that bad currently as we can use the pre-grouped syntax and write

x = range(-π, π, length=100)
y = sin.(x)

mapping([x] => "x", [y] => "y") * visual(Lines) |> draw

image

or more complex:

mapping([x] => "x", [sin.(x), cos.(x)] => "y", color=["sin", "cos"]) * visual(Lines) |> draw

image

What I see missing is

  1. Support for mapping(x, y) as shorthand for mapping([x], [y])

    Maybe also support matrices. For example if A = [a1 a2] is a two-column matrix, mapping(A) could be a shorthand for mapping([[a1] [a2]]).

  2. A way to unlink axes (#203), to support unrelated subplots such as

    a = 0:0.1:3
    b = 5:0.1:7
    mapping([a, b], [sin.(a), sqrt.(b)], layout=["sin", "sqrt"]) *
    visual(Lines) |> draw
    
  3. Some bug(?)fixes as the following don't seem to work:

    • mapping([x], [sin.(x), cos.(x)], layout=["sin", "cos"]) works but with col it gives InexactError: trunc(Int64, NaN)
    • mapping([x], [sin.(x), cos.(x)], color=dims(1)) works but it fails with [sin.(x), cos.(x)] => "y" (gives only one color, and with .=> it produces garbage).
    • mapping([a, b] => ["a", "b"], [sin.(a), sqrt.(b)], layout=["sin", "sqrt"]) fails with MethodError: objects of type Vector{String} are not callable, and with .=> it produces garbage.

knuesel avatar Jun 10 '21 15:06 knuesel

Regarding the support for mapping(x, y) as shorthand for mapping([x], [y]), I thought it could be useful to have a list of accepted types, to see how this would fit.

Here's what I found based on the documentation (these are actually valid types that could be used in dispatch):

  • StringLike and Pair{<:StringLike}: Name of a data column.

    Examples:

    • :x
    • :h => "Height"
    • :y => log => "y"
  • Array{<:StringLike} and Array{<:Pair{<:StringLike}}: Names of data columns (for wide data).

    Examples:

    • [:a, :b, :c]
    • [:a, :b, :c] .=> "some label"
    • [:a :b :c] (for dims(2))
  • DimsSelector and Pair{<:DimsSelector}: Index identifying a dimension in the group space.

    Examples:

    • dims(1)
    • dims(1) => renamer(["Trace 1", "Trace 2"])
  • Pair{<:Tuple{Vararg{StringLike}}}: Names of data columns (for creating new column on the fly).

    Example:

    • (:x, :y, :z) => (+) => "x + y + z"
  • Array{<:Vector}: Data itself as an array of groups (for pre-grouped data).

    Example:

    • [rand(10) for i in 1:3]
    • [[rand(10) for i in 1:3] [rand(10) for i in 1:3]]
  • Pair{<:Tuple{Vararg{Array{<:Vector}}}}: Data itself as arrays of groups (for on the fly column from pre-grouped data).

    Example:

    • ([rand(10) for i in 1:3], [rand(10) for i in 1:3]) => (+) => "sum"

It seems that Array{<:Number} and Pair{<:Array{<:Number}} would fit nicely without ambiguity?

knuesel avatar Jun 10 '21 15:06 knuesel

Nice tip to use mapping([x] => "x", [y] => "y") * visual(Lines). :smile: You can also use mapping([x] => :x, [y] => :y) * visual(Lines), by the way.

rikhuijzer avatar Jun 11 '21 10:06 rikhuijzer