Skip to content

Commit

Permalink
add sorter (#190)
Browse files Browse the repository at this point in the history
* add sorter

* optimize and test renamer
  • Loading branch information
Pietro Vertechi authored May 22, 2021
1 parent efb5430 commit 3243d39
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "AlgebraOfGraphics"
uuid = "cbdf2221-f076-402e-a563-3d30da359d67"
authors = ["Pietro Vertechi <[email protected]>"]
version = "0.4.0"
version = "0.4.1"

[deps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Expand Down
7 changes: 5 additions & 2 deletions docs/src/layers/mappings.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,18 @@ either rename and reorder *unique values* of a categorical column on the fly or
signal that a numerical column should be treated as categorical.

```@docs
AlgebraOfGraphics.renamer
AlgebraOfGraphics.nonnumeric
renamer
sorter
nonnumeric
```

### Examples

```julia
# column `train` has two unique values, `true` and `false`
:train => renamer(true => "training", false => "testing") => "Dataset"
# column `price` has three unique values, `"low"`, `"medium"`, and `"high"`
:price => sorter("low", "medium", "high")
# column `age` is expressed in integers and we want to treat it as categorical
:age => nonnumeric
```
2 changes: 1 addition & 1 deletion src/AlgebraOfGraphics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import FileIO

export hideinnerdecorations!, deleteemptyaxes!
export Entry, AxisEntries
export renamer, nonnumeric
export renamer, sorter, nonnumeric
export density, histogram, linear, smooth, expectation, frequency
export visual, data, geodata, dims, mapping
export draw, draw!
Expand Down
31 changes: 24 additions & 7 deletions src/helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ struct Sorted{T}
idx::UInt32
value::T
end
Sorted(idx::Integer, value) = Sorted(convert(UInt32, idx), value)

Base.print(io::IO, s::Sorted) = print(io, s.value)
Base.isless(s1::Sorted, s2::Sorted) = isless((s1.idx, s1.value), (s2.idx, s2.value))
Expand All @@ -11,6 +12,17 @@ struct Renamer{U, L}
labels::L
end

function (r::Renamer)(x)
for i in keys(r.uniquevalues)
cand = @inbounds r.uniquevalues[i]
if isequal(cand, x)
label = r.labels[i]
return Sorted(i, label)
end
end
throw(KeyError(x))
end

"""
renamer(ps::Pair...)
Expand All @@ -19,16 +31,21 @@ The keys of all pairs should be all the unique values of the categorical variabl
the values should be the corresponding labels. The order of `ps` is respected in
the legend.
"""
function renamer(p::Pair, ps::Pair...)
pairs = (p, ps...)
k, v = map(first, pairs), map(last, pairs)
function renamer(ps::Pair...)
k, v = map(first, ps), map(last, ps)
return Renamer(k, v)
end

function (r::Renamer)(x)
i::UInt32 = findfirst(isequal(x), r.uniquevalues)
label = r.labels[i]
return Sorted(i, label)
"""
sorter(ks...)
Utility to reorder a categorical variable, as in `sorter("low", "medium", "high")`.
`ks` should include all the unique values of the categorical variable.
The order of `ks` is respected in the legend.
"""
function sorter(ks...)
vs = map(string, ks)
return Renamer(ks, vs)
end

struct NonNumeric{T}
Expand Down
25 changes: 25 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,28 @@ end
@test entries[6].positional[2] == df.z[df.c .== "c"]
@test entries[6].named[:markersize] == df.w[df.c .== "c"]
end

@testset "helpers" begin
r = renamer("a" => "A", "b" => "B", "c" => "C")
@test r("a") == AlgebraOfGraphics.Sorted(1, "A")
@test r("b") == AlgebraOfGraphics.Sorted(2, "B")
@test r("c") == AlgebraOfGraphics.Sorted(3, "C")
@test_throws KeyError r("d")
@test string(r("a")) == "A"
@test string(r("b")) == "B"
@test string(r("c")) == "C"
@test r("a") < r("b") < r("c")

s = sorter("b", "c", "a")
@test s("a") == AlgebraOfGraphics.Sorted(3, "a")
@test s("b") == AlgebraOfGraphics.Sorted(1, "b")
@test s("c") == AlgebraOfGraphics.Sorted(2, "c")
@test_throws KeyError s("d")
@test string(s("a")) == "a"
@test string(s("b")) == "b"
@test string(s("c")) == "c"
@test s("b") < s("c") < s("a")

@test string(nonnumeric(1)) == "1"
@test isless(nonnumeric(1), nonnumeric(2))
end

2 comments on commit 3243d39

@piever
Copy link
Collaborator

@piever piever commented on 3243d39 May 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/37255

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.4.1 -m "<description of version>" 3243d39369097ab5f797ecfc4ae98125a78e1897
git push origin v0.4.1

Please sign in to comment.