1
- @require Temporal begin
2
- using TableTraits
3
- using DataValues
4
-
5
- immutable TSIterator{T, S}
1
+ struct TSIterator{T, S}
6
2
source:: S
7
3
end
8
4
9
- TableTraits . isiterable (x:: Temporal.TS ) = true
5
+ IteratorInterfaceExtensions . isiterable (x:: Temporal.TS ) = true
10
6
TableTraits. isiterabletable (x:: Temporal.TS ) = true
11
7
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 }
20
9
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)
31
10
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))... }}
35
12
36
- t = eval (t2)
37
-
38
- e_ta = t (ta)
39
-
40
- return e_ta
13
+ return TSIterator {T,S} (ta)
41
14
end
42
15
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 )
45
18
end
46
19
47
- function Base. eltype {T,TS} (iter:: TSIterator{T,TS} )
20
+ function Base. eltype (iter:: TSIterator{T,TS} ) where {T,TS}
48
21
return T
49
22
end
50
23
51
24
Base. eltype (:: Type{TSIterator{T,TS}} ) where {T,TS} = T
52
25
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}
58
27
constructor_call = Expr (:call , :($ T))
59
28
60
- # Add index column
61
- push! (constructor_call. args, :(iter. source. index[i]))
29
+ push! (constructor_call. args, Expr (:tuple ))
62
30
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]))
65
36
end
66
37
67
38
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
71
46
end
72
47
end
73
48
74
- function Base. done {T,TS} (iter:: TSIterator{T,TS} , state)
75
- return state> length (iter. source. index)
76
- end
77
-
78
49
# Sink
79
50
80
- # TODO This is a terribly inefficient implementation. Minimally it
81
- # should be changed to be more type stable.
82
51
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. " )
84
53
85
54
iter = getiterator (x)
86
55
87
- if TableTraits. column_count (iter)< 2
56
+ et = eltype (iter)
57
+
58
+ if fieldcount (et)< 2
88
59
error (" Need at least two columns" )
89
60
end
90
61
91
- names = TableTraits . column_names (iter )
62
+ names = fieldnames (et )
92
63
93
- timestep_col_index = findfirst (names, index_column )
64
+ timestep_col_index = findfirst (isequal (index_column), names )
94
65
95
- if timestep_col_index== 0
96
- error (" No index column found." )
66
+ if timestep_col_index=== nothing
67
+ error (" No timestamp column found." )
97
68
end
69
+
70
+ timestep_col_index = something (timestep_col_index)
98
71
99
- col_types = TableTraits . column_types (iter)
72
+ col_types = [ fieldtype (et, i) for i = 1 : fieldcount (et)]
100
73
101
74
data_columns = collect (Iterators. filter (i-> i[2 ][1 ]!= index_column, enumerate (zip (names, col_types))))
102
75
103
76
orig_data_type = data_columns[1 ][2 ][2 ]
104
77
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
106
79
107
80
orig_timestep_type = col_types[timestep_col_index]
108
81
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
110
83
111
84
if any (i-> i[2 ][2 ]!= orig_data_type, data_columns)
112
85
error (" All data columns need to be of the same type." )
113
86
end
114
87
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 )
117
90
for i in data_columns
118
- push! (d_array, Array {data_type,1} ( ))
91
+ push! (d_array, Vector {data_type} (undef, 0 ))
119
92
end
120
93
121
94
for v in iter
@@ -141,5 +114,3 @@ function Temporal.TS(x; index_column::Symbol=:Index)
141
114
ta = Temporal. TS (d_array, t_column,[i[2 ][1 ] for i in data_columns])
142
115
return ta
143
116
end
144
-
145
- end
0 commit comments