Skip to content

Commit 414fd9b

Browse files
authored
Add 'Compose' transform (#243)
1 parent 2517cf1 commit 414fd9b

File tree

7 files changed

+150
-0
lines changed

7 files changed

+150
-0
lines changed

docs/src/transforms.md

+6
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ Closure
224224
Remainder
225225
```
226226

227+
## Compose
228+
229+
```@docs
230+
Compose
231+
```
232+
227233
## ALR
228234

229235
```@docs

src/TableTransforms.jl

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export
8686
ProjectionPursuit,
8787
Closure,
8888
Remainder,
89+
Compose,
8990
ALR,
9091
CLR,
9192
ILR,

src/transforms.jl

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ include("transforms/eigenanalysis.jl")
293293
include("transforms/projectionpursuit.jl")
294294
include("transforms/closure.jl")
295295
include("transforms/remainder.jl")
296+
include("transforms/compose.jl")
296297
include("transforms/logratio.jl")
297298
include("transforms/rowtable.jl")
298299
include("transforms/coltable.jl")

src/transforms/compose.jl

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# ------------------------------------------------------------------
2+
# Licensed under the MIT License. See LICENSE in the project root.
3+
# ------------------------------------------------------------------
4+
5+
"""
6+
Compose(; as=:CODA)
7+
8+
Converts all columns of the table into parts of a composition
9+
in a new column named `as`, using the `CoDa.compose` function.
10+
11+
Compose(col₁, col₂, ..., colₙ; as=:CODA)
12+
Compose([col₁, col₂, ..., colₙ]; as=:CODA)
13+
Compose((col₁, col₂, ..., colₙ); as=:CODA)
14+
15+
Converts the selected columns `col₁`, `col₂`, ..., `colₙ` into parts of a composition.
16+
17+
Compose(regex; as=:CODA)
18+
19+
Converts the columns that match with `regex` into parts of a composition.
20+
21+
# Examples
22+
23+
```julia
24+
Compose(as=:comp)
25+
Compose([2, 3, 5])
26+
Compose([:b, :c, :e])
27+
Compose(("b", "c", "e"))
28+
Compose(r"[bce]", as="COMP")
29+
```
30+
"""
31+
struct Compose{S<:ColumnSelector} <: StatelessFeatureTransform
32+
selector::S
33+
as::Symbol
34+
end
35+
36+
Compose(selector::ColumnSelector; as=:CODA) = Compose(selector, Symbol(as))
37+
38+
Compose(; kwargs...) = Compose(AllSelector(); kwargs...)
39+
Compose(cols; kwargs...) = Compose(selector(cols); kwargs...)
40+
Compose(cols::C...; kwargs...) where {C<:Column} = Compose(selector(cols); kwargs...)
41+
42+
isrevertible(::Type{<:Compose}) = true
43+
44+
function applyfeat(transform::Compose, feat, prep)
45+
cols = Tables.columns(feat)
46+
names = Tables.columnnames(cols)
47+
snames = transform.selector(names)
48+
as = transform.as
49+
50+
newfeat = compose(feat, snames; as)
51+
52+
newfeat, (names, snames, as)
53+
end
54+
55+
function revertfeat(::Compose, newfeat, fcache)
56+
cols = Tables.columns(newfeat)
57+
names, snames, as = fcache
58+
59+
coda = Tables.getcolumn(cols, as)
60+
columns = map(names) do name
61+
if name snames
62+
Tables.getcolumn(coda, name)
63+
else
64+
Tables.getcolumn(cols, name)
65+
end
66+
end
67+
68+
𝒯 = (; zip(names, columns)...)
69+
𝒯 |> Tables.materializer(newfeat)
70+
end

test/shows.jl

+15
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,21 @@
399399
└─ total = nothing"""
400400
end
401401

402+
@testset "Compose" begin
403+
T = Compose(:a, :b, :c)
404+
405+
# compact mode
406+
iostr = sprint(show, T)
407+
@test iostr == "Compose([:a, :b, :c], :CODA)"
408+
409+
# full mode
410+
iostr = sprint(show, MIME("text/plain"), T)
411+
@test iostr == """
412+
Compose transform
413+
├─ selector = [:a, :b, :c]
414+
└─ as = :CODA"""
415+
end
416+
402417
@testset "RowTable" begin
403418
T = RowTable()
404419

test/transforms.jl

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ transformfiles = [
2828
"projectionpursuit.jl",
2929
"closure.jl",
3030
"remainder.jl",
31+
"compose.jl",
3132
"logratio.jl",
3233
"rowtable.jl",
3334
"coltable.jl",

test/transforms/compose.jl

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
@testset "Compose" begin
2+
@test isrevertible(Compose())
3+
4+
a = rand(10)
5+
b = rand(10)
6+
c = rand(10)
7+
t = Table(; a, b, c)
8+
9+
T = Compose()
10+
n, c = apply(T, t)
11+
@test Tables.schema(n).names == (:CODA,)
12+
@test n.CODA isa CoDaArray
13+
@test n.CODA == CoDaArray(t)
14+
tₒ = revert(T, n, c)
15+
@test tₒ == t
16+
17+
T = Compose(as=:comp)
18+
n, c = apply(T, t)
19+
@test Tables.schema(n).names == (:comp,)
20+
@test n.comp isa CoDaArray
21+
@test n.comp == CoDaArray(t)
22+
tₒ = revert(T, n, c)
23+
@test tₒ == t
24+
25+
T = Compose(1, 2)
26+
n, c = apply(T, t)
27+
@test Tables.schema(n).names == (:c, :CODA)
28+
@test n.CODA isa CoDaArray
29+
@test n.CODA == CoDaArray((a=t.a, b=t.b))
30+
tₒ = revert(T, n, c)
31+
@test tₒ == t
32+
33+
T = Compose([:a, :c])
34+
n, c = apply(T, t)
35+
@test Tables.schema(n).names == (:b, :CODA)
36+
@test n.CODA isa CoDaArray
37+
@test n.CODA == CoDaArray((a=t.a, c=t.c))
38+
tₒ = revert(T, n, c)
39+
@test tₒ == t
40+
41+
T = Compose(("b", "c"))
42+
n, c = apply(T, t)
43+
@test Tables.schema(n).names == (:a, :CODA)
44+
@test n.CODA isa CoDaArray
45+
@test n.CODA == CoDaArray((b=t.b, c=t.c))
46+
tₒ = revert(T, n, c)
47+
@test tₒ == t
48+
49+
T = Compose(r"[ab]", as="COMP")
50+
n, c = apply(T, t)
51+
@test Tables.schema(n).names == (:c, :COMP)
52+
@test n.COMP isa CoDaArray
53+
@test n.COMP == CoDaArray((a=t.a, b=t.b))
54+
tₒ = revert(T, n, c)
55+
@test tₒ == t
56+
end

0 commit comments

Comments
 (0)