Skip to content

Commit

Permalink
Support RowTable
Browse files Browse the repository at this point in the history
Note that we cannot call `apply!` on rowtables since the elements
of the NamedTuple rows are immutable in this instance.

e.g. row = NamedTuple{(:a, :b)}(a=1, b=2)

convert to-from a columntable defeats the purpose as it wouldn't be
mutating the underlying table.
  • Loading branch information
Glenn Moynihan committed Jul 8, 2021
1 parent cdb209a commit 5c27b10
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FeatureTransforms"
uuid = "8fd68953-04b8-4117-ac19-158bf6de9782"
authors = ["Invenia Technical Computing Corporation"]
version = "0.3.7"
version = "0.3.8"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
25 changes: 21 additions & 4 deletions src/apply.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,35 @@ function apply(table, t::Transform; cols=_get_cols(table), header=nothing, kwarg
return Tables.materializer(table)(_to_table(result, header))
end

# Prevents Vector{NamedTuple} from using the AbstractArray method above
function apply(table::Tables.RowTable, t::Transform; kwargs...)
return rowtable(apply(Tables.columntable(table), t; kwargs...))
end

"""
apply!(table::T, ::Transform; [cols])::T where T
Applies the [`Transform`](@ref) to each of the specified columns in the `table`.
If no `cols` are specified, then the [`Transform`](@ref) is applied to all columns.
!!! Note
`apply!` does not support `RowTable`s since the `NamedTuple` rows are immutable.
"""
function apply!(table::T, t::Transform; cols=_get_cols(table), kwargs...)::T where T
Tables.istable(table) || throw(MethodError(apply!, (table, t)))

# Extract a columns iterator that we should be able to use to mutate the data.
# NOTE: Mutation is not guaranteed for all table types, but it avoid copying the data
coltable = Tables.columntable(table)
for cname in _to_vec(cols)
apply!(getproperty(coltable, cname), t; kwargs...)
apply!(getproperty(table, cname), t; kwargs...)
end

return table
end

# Prevents Vector{NamedTuple} from using the AbstractArray method above
function apply!(table::Tables.RowTable, t::Transform; kwargs...)
return throw(MethodError(apply!, (table, t)))
end

"""
apply_append(A::AbstractArray, ::Transform; append_dim, kwargs...)
Expand Down Expand Up @@ -135,6 +145,13 @@ function apply_append(table, t; kwargs...)
return T(merge(Tables.columntable(table), result))
end

# Prevents Vector{NamedTuple} from using the AbstractArray method above
function apply_append(table::Tables.RowTable, t; kwargs...)
T = Tables.materializer(table)
result = apply(table, t; kwargs...)
return T(merge.(Tables.rowtable(table), result))
end

# These methods format data according to the cardinality of the Transform.
# Most Transforms don't require any formatting, only those that are ManyToOne do.
# Note: we don't yet have a ManyToMany transform, so those might need separate treatment.
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ using FeatureTransforms
using FeatureTransforms: _periodic
using FeatureTransforms: cardinality, OneToOne, OneToMany, ManyToOne, ManyToMany
using FeatureTransforms.TestUtils
using Tables: columntable, istable, rowtable
using Tables: columntable, isrowtable, istable, rowtable
using Test
using TimeZones

Expand Down
30 changes: 17 additions & 13 deletions test/types/tables.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# TODO: test on rowtable https://github.com/invenia/FeatureTransforms.jl/issues/64
@testset "$TableType" for TableType in (columntable, DataFrame)
@testset "$TableType" for TableType in (columntable, rowtable, DataFrame)

table = TableType((a=[1, 2, 3], b=[4, 5, 6]))

Expand Down Expand Up @@ -91,17 +90,22 @@
@testset "apply!" begin
T = FakeOneToOneTransform()

_table = deepcopy(table)
FeatureTransforms.apply!(_table, T)
@test _table == TableType((a=ones(3), b=ones(3)))

_table = deepcopy(table)
FeatureTransforms.apply!(_table, T; cols=:a)
@test _table == TableType((a=[1, 1, 1], b=[4, 5, 6]))

_table = deepcopy(table)
@test_broken FeatureTransforms.apply!(_table, T; cols=:b, dims=[1, 2])
@test_broken _table == TableType((a=[1, 2, 3], b=[1, 1, 6]))
# Cannot mutate NamedTuple elements
if isrowtable(table)
@test_throws MethodError FeatureTransforms.apply!(table, T)
else
_table = deepcopy(table)
FeatureTransforms.apply!(_table, T)
@test _table == TableType((a=ones(3), b=ones(3)))

_table = deepcopy(table)
FeatureTransforms.apply!(_table, T; cols=:a)
@test _table == TableType((a=[1, 1, 1], b=[4, 5, 6]))

_table = deepcopy(table)
@test_broken FeatureTransforms.apply!(_table, T; cols=:b, dims=[1, 2])
@test_broken _table == TableType((a=[1, 2, 3], b=[1, 1, 6]))
end
end

@testset "apply_append" begin
Expand Down

0 comments on commit 5c27b10

Please sign in to comment.