Skip to content

Commit 30d9030

Browse files
committed
Enable Temporal.jl integration again
1 parent adbdc38 commit 30d9030

File tree

5 files changed

+47
-83
lines changed

5 files changed

+47
-83
lines changed

src/IterableTables.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ using DataValues
66
# include("integrations/gadfly.jl")
77
# include("integrations/juliadb.jl")
88
include("integrations/generators.jl")
9-
# include("integrations/temporal.jl")
109

1110
function __init__()
1211
@require DataFrames="a93c6f00-e57d-5684-b7b6-d8193f3e46c0" if !isdefined(DataFrames, :Tables)
1312
include("integrations/dataframes.jl")
1413
end
1514
@require StatsModels="3eaba693-59b7-5ba5-a881-562e759f1c8d" include("integrations/statsmodels.jl")
1615
@require TimeSeries="9e3dc215-6440-5c97-bce1-76c03772f85e" include("integrations/timeseries.jl")
16+
@require Temporal="a110ec8f-48c8-5d59-8f7e-f91bc4cc0c3d" include("integrations/temporal.jl")
1717
end
1818

1919
end # module

src/integrations/temporal.jl

+38-67
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,94 @@
1-
@require Temporal begin
2-
using TableTraits
3-
using DataValues
4-
5-
immutable TSIterator{T, S}
1+
struct TSIterator{T, S}
62
source::S
73
end
84

9-
TableTraits.isiterable(x::Temporal.TS) = true
5+
IteratorInterfaceExtensions.isiterable(x::Temporal.TS) = true
106
TableTraits.isiterabletable(x::Temporal.TS) = true
117

12-
function TableTraits.getiterator{S<:Temporal.TS}(ta::S)
13-
col_expressions = Array{Expr,1}()
14-
df_columns_tuple_type = Expr(:curly, :Tuple)
15-
16-
# Add column for index
17-
push!(col_expressions, Expr(:(::), :Index, S.parameters[2]))
18-
push!(df_columns_tuple_type.args, S.parameters[2])
19-
8+
function IteratorInterfaceExtensions.getiterator(ta::S) where {S<:Temporal.TS}
209
etype = eltype(ta.values)
21-
if ndims(ta.values)==1
22-
push!(col_expressions, Expr(:(::), ta.fields[1], etype))
23-
push!(df_columns_tuple_type.args, etype)
24-
else
25-
for i in 1:size(ta.values,2)
26-
push!(col_expressions, Expr(:(::), Symbol(ta.fields[i]), etype))
27-
push!(df_columns_tuple_type.args, etype)
28-
end
29-
end
30-
t_expr = NamedTuples.make_tuple(col_expressions)
3110

32-
t2 = :(TSIterator{Float64,Float64})
33-
t2.args[2] = t_expr
34-
t2.args[3] = S
11+
T = NamedTuple{(:Index, ta.fields...), Tuple{eltype(ta.index), fill(etype, length(ta.fields))...}}
3512

36-
t = eval(t2)
37-
38-
e_ta = t(ta)
39-
40-
return e_ta
13+
return TSIterator{T,S}(ta)
4114
end
4215

43-
function Base.length{T,TS}(iter::TSIterator{T,TS})
44-
return length(iter.source)
16+
function Base.length(iter::TSIterator)
17+
return length(iter.source.index)
4518
end
4619

47-
function Base.eltype{T,TS}(iter::TSIterator{T,TS})
20+
function Base.eltype(iter::TSIterator{T,TS}) where {T,TS}
4821
return T
4922
end
5023

5124
Base.eltype(::Type{TSIterator{T,TS}}) where {T,TS} = T
5225

53-
function Base.start{T,TS}(iter::TSIterator{T,TS})
54-
return 1
55-
end
56-
57-
@generated function Base.next{T,S}(iter::TSIterator{T,S}, state)
26+
@generated function Base.iterate(iter::TSIterator{T,TS}, state=1) where {T,TS}
5827
constructor_call = Expr(:call, :($T))
5928

60-
# Add index column
61-
push!(constructor_call.args, :(iter.source.index[i]))
29+
push!(constructor_call.args, Expr(:tuple))
6230

63-
for i in 1:length(T.parameters)-1
64-
push!(constructor_call.args, :(iter.source.values[i,$i]))
31+
# Add timestamp column
32+
push!(constructor_call.args[2].args, :(iter.source.index[i]))
33+
34+
for i in 1:fieldcount(T)-1
35+
push!(constructor_call.args[2].args, :(iter.source.values[i,$i]))
6536
end
6637

6738
quote
68-
i = state
69-
a = $constructor_call
70-
return a, state+1
39+
if state>length(iter.source.index)
40+
return nothing
41+
else
42+
i = state
43+
a = $constructor_call
44+
return a, state+1
45+
end
7146
end
7247
end
7348

74-
function Base.done{T,TS}(iter::TSIterator{T,TS}, state)
75-
return state>length(iter.source.index)
76-
end
77-
7849
# Sink
7950

80-
# TODO This is a terribly inefficient implementation. Minimally it
81-
# should be changed to be more type stable.
8251
function Temporal.TS(x; index_column::Symbol=:Index)
83-
isiterabletable(x) || error()
52+
TableTraits.isiterabletable(x) || error("Cannot create a TS from something that is not a table.")
8453

8554
iter = getiterator(x)
8655

87-
if TableTraits.column_count(iter)<2
56+
et = eltype(iter)
57+
58+
if fieldcount(et)<2
8859
error("Need at least two columns")
8960
end
9061

91-
names = TableTraits.column_names(iter)
62+
names = fieldnames(et)
9263

93-
timestep_col_index = findfirst(names, index_column)
64+
timestep_col_index = findfirst(isequal(index_column), names)
9465

95-
if timestep_col_index==0
96-
error("No index column found.")
66+
if timestep_col_index===nothing
67+
error("No timestamp column found.")
9768
end
69+
70+
timestep_col_index = something(timestep_col_index)
9871

99-
col_types = TableTraits.column_types(iter)
72+
col_types = [fieldtype(et, i) for i=1:fieldcount(et)]
10073

10174
data_columns = collect(Iterators.filter(i->i[2][1]!=index_column, enumerate(zip(names, col_types))))
10275

10376
orig_data_type = data_columns[1][2][2]
10477

105-
data_type = orig_data_type <: DataValue ? orig_data_type.parameters[1] : orig_data_type
78+
data_type = orig_data_type <: DataValues.DataValue ? orig_data_type.parameters[1] : orig_data_type
10679

10780
orig_timestep_type = col_types[timestep_col_index]
10881

109-
timestep_type = orig_timestep_type <: DataValue ? orig_timestep_type.parameters[1] : orig_timestep_type
82+
timestep_type = orig_timestep_type <: DataValues.DataValue ? orig_timestep_type.parameters[1] : orig_timestep_type
11083

11184
if any(i->i[2][2]!=orig_data_type, data_columns)
11285
error("All data columns need to be of the same type.")
11386
end
11487

115-
t_column = Array{timestep_type,1}()
116-
d_array = Array{Array{data_type,1},1}()
88+
t_column = Vector{timestep_type}(undef,0)
89+
d_array = Vector{Vector{data_type}}(undef,0)
11790
for i in data_columns
118-
push!(d_array, Array{data_type,1}())
91+
push!(d_array, Vector{data_type}(undef,0))
11992
end
12093

12194
for v in iter
@@ -141,5 +114,3 @@ function Temporal.TS(x; index_column::Symbol=:Index)
141114
ta = Temporal.TS(d_array, t_column,[i[2][1] for i in data_columns])
142115
return ta
143116
end
144-
145-
end

test/REQUIRE

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ StatsModels
33
TimeSeries
44
# Gadfly
55
GLM
6-
# Temporal
6+
Temporal
77
# JuliaDB

test/runtests.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ include("test_integration_dataframes.jl")
99
# TODO Reenable once GLM is 0.7 compatible
1010
# include("test_integration_statsmodels.jl")
1111
include("test_integration_timeseries.jl")
12-
# include("test_integration_temporal.jl")
12+
include("test_integration_temporal.jl")
1313
# include("test_integration_juliadb.jl")
1414
# include("test_integration_gadfly.jl")
1515

test/test_integration_temporal.jl

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
using IterableTables
2-
using NamedTuples
2+
using IteratorInterfaceExtensions
3+
using TableTraits
34
using Temporal
45
using DataFrames
5-
using NullableArrays
6-
import TypedTables
7-
using Base.Test
6+
using Test
87

98
@testset "Temporal" begin
109

11-
dates = collect(Date(1999,1,1):Date(1999,1,3))
10+
dates = collect(Date(1999,1,1):Day(1):Date(1999,1,3))
1211

1312
source_ta1 = TS(collect(1:length(dates)), dates, [:value])
1413

15-
@test isiterable(source_ta1) == true
14+
@test IteratorInterfaceExtensions.isiterable(source_ta1) == true
1615

17-
source_it = getiterator(source_ta1)
16+
source_it = IteratorInterfaceExtensions.getiterator(source_ta1)
1817

1918
@test length(source_it) == 3
2019

@@ -43,12 +42,6 @@ df4 = DataFrame(source_ta4)
4342
@test df4[:a] == [1,2,3]
4443
@test df4[:b] == [3,2,1]
4544

46-
source_tt = TypedTables.@Table(a=[4.,5.], time=[Date(1999,1,1),Date(1999,1,2)], b=[6.,8.], c=[12.,24.])
47-
ta1 = TS(source_tt, index_column=:time)
48-
@test size(ta1) == (2,3)
49-
@test ta1.values == [4. 6. 12.;5. 8. 24]
50-
@test ta1.index == [Date(1999,1,1),Date(1999,1,2)]
51-
5245
source_df = DataFrame(a=[4.,5.], Index=[Date(1999,1,1),Date(1999,1,2)], b=[6.,8.])
5346
ta2 = TS(source_df)
5447
@test size(ta2) == (2,2)

0 commit comments

Comments
 (0)