Skip to content

Commit ec9b98b

Browse files
authored
Return target columns in Map (#302)
* Return target columns in Map * Remove unnecessary collect
1 parent 52a900d commit ec9b98b

File tree

2 files changed

+38
-57
lines changed

2 files changed

+38
-57
lines changed

src/transforms/map.jl

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
# Licensed under the MIT License. See LICENSE in the project root.
33
# ------------------------------------------------------------------
44

5+
const TargetName = Union{Symbol,AbstractString}
6+
const PairWithTarget = Pair{<:Any,<:Pair{<:Function,<:TargetName}}
7+
const PairWithoutTarget = Pair{<:Any,<:Function}
8+
const MapPair = Union{PairWithTarget,PairWithoutTarget}
9+
510
"""
611
Map(cols₁ => fun₁ => target₁, cols₂ => fun₂, ..., colsₙ => funₙ => targetₙ)
712
@@ -13,8 +18,6 @@ a collection of identifiers or a regular expression (regex).
1318
1419
Passing a target column name is optional and when omitted a new name
1520
is generated by joining the function name with the selected column names.
16-
If the target column already exists in the table, the original
17-
column will be replaced.
1821
1922
## Examples
2023
@@ -44,16 +47,6 @@ end
4447

4548
Map() = throw(ArgumentError("cannot create Map transform without arguments"))
4649

47-
# utility types
48-
const TargetName = Union{Symbol,AbstractString}
49-
const PairWithTarget = Pair{<:Any,<:Pair{<:Function,<:TargetName}}
50-
const PairWithoutTarget = Pair{<:Any,<:Function}
51-
const MapPair = Union{PairWithTarget,PairWithoutTarget}
52-
53-
# utility functions
54-
_extract(p::PairWithTarget) = selector(first(p)), first(last(p)), Symbol(last(last(p)))
55-
_extract(p::PairWithoutTarget) = selector(first(p)), last(p), nothing
56-
5750
function Map(pairs::MapPair...)
5851
tuples = map(_extract, pairs)
5952
selectors = [t[1] for t in tuples]
@@ -62,32 +55,14 @@ function Map(pairs::MapPair...)
6255
Map(selectors, funs, targets)
6356
end
6457

65-
_funname(fun::Base.Fix1) = "fix1_" * _funname(fun.f)
66-
_funname(fun::Base.Fix2) = "fix2_" * _funname(fun.f)
67-
_funname(fun::ComposedFunction) = _funname(fun.outer) * "_" * _funname(fun.inner)
68-
_funname(fun) = string(fun)
69-
70-
function _makename(snames, fun)
71-
funname = _funname(fun)
72-
if contains(funname, "#") # anonymous functions
73-
funname = replace(funname, "#" => "f")
74-
end
75-
Symbol(funname, :_, join(snames, "_"))
76-
end
77-
7858
function applyfeat(transform::Map, feat, prep)
7959
cols = Tables.columns(feat)
80-
onames = Tables.columnnames(cols)
60+
names = Tables.columnnames(cols)
8161

8262
selectors = transform.selectors
8363
funs = transform.funs
8464
targets = transform.targets
8565

86-
# new names and columns
87-
names = collect(onames)
88-
columns = Any[Tables.getcolumn(cols, nm) for nm in onames]
89-
90-
# mapped columns
9166
mapped = map(selectors, funs, targets) do selector, fun, target
9267
snames = selector(names)
9368
newname = isnothing(target) ? _makename(snames, fun) : target
@@ -96,17 +71,23 @@ function applyfeat(transform::Map, feat, prep)
9671
newname => newcolumn
9772
end
9873

99-
for (name, column) in mapped
100-
if name onames
101-
i = findfirst(==(name), onames)
102-
columns[i] = column
103-
else
104-
push!(names, name)
105-
push!(columns, column)
106-
end
107-
end
74+
newfeat = (; mapped...) |> Tables.materializer(feat)
10875

109-
𝒯 = (; zip(names, columns)...)
110-
newfeat = 𝒯 |> Tables.materializer(feat)
11176
newfeat, nothing
11277
end
78+
79+
_extract(p::PairWithTarget) = selector(first(p)), first(last(p)), Symbol(last(last(p)))
80+
_extract(p::PairWithoutTarget) = selector(first(p)), last(p), nothing
81+
82+
_funname(fun::Base.Fix1) = "fix1_" * _funname(fun.f)
83+
_funname(fun::Base.Fix2) = "fix2_" * _funname(fun.f)
84+
_funname(fun::ComposedFunction) = _funname(fun.outer) * "_" * _funname(fun.inner)
85+
_funname(fun) = string(fun)
86+
87+
function _makename(snames, fun)
88+
funname = _funname(fun)
89+
if contains(funname, "#") # anonymous functions
90+
funname = replace(funname, "#" => "f")
91+
end
92+
Symbol(funname, :_, join(snames, "_"))
93+
end

test/transforms/map.jl

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,55 @@
99

1010
T = Map(1 => sin)
1111
n, c = apply(T, t)
12-
@test Tables.schema(n).names == (:a, :b, :c, :d, :sin_a)
12+
@test Tables.schema(n).names == (:sin_a,)
1313
@test n.sin_a == sin.(t.a)
1414

1515
T = Map(:b => cos)
1616
n, c = apply(T, t)
17-
@test Tables.schema(n).names == (:a, :b, :c, :d, :cos_b)
17+
@test Tables.schema(n).names == (:cos_b,)
1818
@test n.cos_b == cos.(t.b)
1919

2020
T = Map("c" => tan)
2121
n, c = apply(T, t)
22-
@test Tables.schema(n).names == (:a, :b, :c, :d, :tan_c)
22+
@test Tables.schema(n).names == (:tan_c,)
2323
@test n.tan_c == tan.(t.c)
2424

2525
T = Map(:a => sin => :a)
2626
n, c = apply(T, t)
27-
@test Tables.schema(n).names == (:a, :b, :c, :d)
27+
@test Tables.schema(n).names == (:a,)
2828
@test n.a == sin.(t.a)
2929

3030
T = Map(:a => sin => "a")
3131
n, c = apply(T, t)
32-
@test Tables.schema(n).names == (:a, :b, :c, :d)
32+
@test Tables.schema(n).names == (:a,)
3333
@test n.a == sin.(t.a)
3434

3535
T = Map([2, 3] => ((b, c) -> 2b + c) => :op1)
3636
n, c = apply(T, t)
37-
@test Tables.schema(n).names == (:a, :b, :c, :d, :op1)
37+
@test Tables.schema(n).names == (:op1,)
3838
@test n.op1 == @. 2 * t.b + t.c
3939

4040
T = Map([:a, :c] => ((a, c) -> 2a * 3c) => :op1)
4141
n, c = apply(T, t)
42-
@test Tables.schema(n).names == (:a, :b, :c, :d, :op1)
42+
@test Tables.schema(n).names == (:op1,)
4343
@test n.op1 == @. 2 * t.a * 3 * t.c
4444

4545
T = Map(["c", "a"] => ((c, a) -> 3c / a) => :op1, "c" => tan)
4646
n, c = apply(T, t)
47-
@test Tables.schema(n).names == (:a, :b, :c, :d, :op1, :tan_c)
47+
@test Tables.schema(n).names == (:op1, :tan_c)
4848
@test n.op1 == @. 3 * t.c / t.a
4949
@test n.tan_c == tan.(t.c)
5050

5151
T = Map(r"[abc]" => ((a, b, c) -> a^2 - 2b + c) => "op1")
5252
n, c = apply(T, t)
53-
@test Tables.schema(n).names == (:a, :b, :c, :d, :op1)
53+
@test Tables.schema(n).names == (:op1,)
5454
@test n.op1 == @. t.a^2 - 2 * t.b + t.c
5555

5656
# generated names
5757
# normal function
5858
T = Map([:c, :d] => hypot)
5959
n, c = apply(T, t)
60-
@test Tables.schema(n).names == (:a, :b, :c, :d, :hypot_c_d)
60+
@test Tables.schema(n).names == (:hypot_c_d,)
6161
@test n.hypot_c_d == hypot.(t.c, t.d)
6262

6363
# anonymous function
@@ -66,34 +66,34 @@
6666
colname = Symbol(fname, :_a)
6767
T = Map(:a => f)
6868
n, c = apply(T, t)
69-
@test Tables.schema(n).names == (:a, :b, :c, :d, colname)
69+
@test Tables.schema(n).names == (colname,)
7070
@test Tables.getcolumn(n, colname) == f.(t.a)
7171

7272
# composed function
7373
f = sin cos
7474
T = Map(:b => f)
7575
n, c = apply(T, t)
76-
@test Tables.schema(n).names == (:a, :b, :c, :d, :sin_cos_b)
76+
@test Tables.schema(n).names == (:sin_cos_b,)
7777
@test n.sin_cos_b == f.(t.b)
7878

7979
f = sin cos tan
8080
T = Map(:c => sin cos tan)
8181
n, c = apply(T, t)
82-
@test Tables.schema(n).names == (:a, :b, :c, :d, :sin_cos_tan_c)
82+
@test Tables.schema(n).names == (:sin_cos_tan_c,)
8383
@test n.sin_cos_tan_c == f.(t.c)
8484

8585
# Base.Fix1
8686
f = Base.Fix1(hypot, 2)
8787
T = Map(:d => f)
8888
n, c = apply(T, t)
89-
@test Tables.schema(n).names == (:a, :b, :c, :d, :fix1_hypot_d)
89+
@test Tables.schema(n).names == (:fix1_hypot_d,)
9090
@test n.fix1_hypot_d == f.(t.d)
9191

9292
# Base.Fix2
9393
f = Base.Fix2(hypot, 2)
9494
T = Map(:a => f)
9595
n, c = apply(T, t)
96-
@test Tables.schema(n).names == (:a, :b, :c, :d, :fix2_hypot_a)
96+
@test Tables.schema(n).names == (:fix2_hypot_a,)
9797
@test n.fix2_hypot_a == f.(t.a)
9898

9999
# error: cannot create Map transform without arguments

0 commit comments

Comments
 (0)