11__precompile__ ()
22module TableTraitsUtils
33
4- using TableTraits, NamedTuples , DataValues
4+ using IteratorInterfaceExtensions, TableTraits , DataValues, Missings
55
66export create_tableiterator, create_columns_from_iterabletable
77
@@ -12,71 +12,45 @@ struct TableIterator{T, TS}
1212end
1313
1414function create_tableiterator (columns, names:: Vector{Symbol} )
15- col_expressions = Array {Expr,1} ()
16- df_columns_tuple_type = Expr (:curly , :Tuple )
17- for i in 1 : length (columns)
18- etype = eltype (columns[i])
19- if etype <: Nullable
20- push! (col_expressions, Expr (:(:: ), names[i], DataValue{etype. parameters[1 ]}))
15+ field_types = Type[]
16+ for i in eltype .(columns)
17+ if i >: Missing
18+ push! (field_types, DataValue{Missings. T (i)})
2119 else
22- push! (col_expressions, Expr (:( :: ), names[i], etype) )
20+ push! (field_types, i )
2321 end
24- push! (df_columns_tuple_type. args, typeof (columns[i]))
2522 end
26- t_expr = NamedTuples. make_tuple (col_expressions)
27-
28- t2 = :(TableIterator{Float64,Float64})
29- t2. args[2 ] = t_expr
30- t2. args[3 ] = df_columns_tuple_type
31-
32- t = eval (t2)
33-
34- e_df = t ((columns... ))
35-
36- return e_df
23+ return TableIterator {NamedTuple{(names...,), Tuple{field_types...}}, Tuple{typeof.(columns)...}} ((columns... ,))
3724end
3825
3926function Base. length (iter:: TableIterator{T,TS} ) where {T,TS}
4027 return length (iter. columns[1 ])
4128end
4229
43- function Base. eltype (iter:: TableIterator{T,TS} ) where {T,TS}
44- return T
45- end
46-
4730Base. eltype (:: Type{TableIterator{T,TS}} ) where {T,TS} = T
4831
49- function Base. start (iter:: TableIterator{T,TS} ) where {T,TS}
50- return 1
51- end
52-
53- @generated function Base. next (iter:: TableIterator{T,TS} , state) where {T,TS}
54- constructor_call = Expr (:call , :($ T))
55- for (i,t) in enumerate (T. parameters)
56- if eltype (iter. parameters[2 ]. parameters[i]) <: Nullable
57- push! (constructor_call. args, :(DataValue (columns[$ i][i])))
32+ @generated function Base. iterate (iter:: TableIterator{T,TS} , state= 1 ) where {T,TS}
33+ columns = map (1 : length (TS. parameters)) do i
34+ if fieldtype (T,i) <: DataValue && eltype (TS. parameters[i]) >: Missing
35+ return :($ (fieldtype (T,i))(iter. columns[$ i][state]))
5836 else
59- push! (constructor_call . args, :(columns[$ i][i]) )
37+ return :(iter . columns[$ i][state] )
6038 end
6139 end
62-
63- quote
64- i = state
65- columns = iter . columns
66- a = $ constructor_call
67- return a, state + 1
40+ return quote
41+ if state > length (iter)
42+ return nothing
43+ else
44+ return $ (T)(( $ (columns ... ),)), state + 1
45+ end
6846 end
6947end
7048
71- function Base. done (iter:: TableIterator{T,TS} , state) where {T,TS}
72- return state> length (iter. columns[1 ])
73- end
74-
7549# Sink
7650
7751@generated function _fill_cols_without_length (columns, enumerable)
7852 push_exprs = Expr (:block )
79- for i in find (collect (columns. types) .!= Void )
53+ for i in findall (collect (columns. types) .!= Nothing )
8054 ex = :( push! (columns[$ i], i[$ i]) )
8155 push! (push_exprs. args, ex)
8256 end
9064
9165@generated function _fill_cols_with_length (columns, enumerable)
9266 push_exprs = Expr (:block )
93- for col_idx in find (collect (columns. types) .!= Void )
67+ for col_idx in findall (collect (columns. types) .!= Nothing )
9468 ex = :( columns[$ col_idx][i] = v[$ col_idx] )
9569 push! (push_exprs. args, ex)
9670 end
10276 end
10377end
10478
105- function _default_array_factory (t,rows)
106- if isa (t, TypeVar)
107- return Array {Any} (rows)
108- else
109- return Array {t} (rows)
110- end
111- end
112-
113- function create_columns_from_iterabletable (source, sel_cols = :all ; array_factory:: Function = _default_array_factory)
79+ function create_columns_from_iterabletable (source; sel_cols= :all , na_representation= :datavalue )
11480 iter = getiterator (source)
11581
11682 T = eltype (iter)
11783 if ! (T<: NamedTuple )
11884 error (" Can only collect a NamedTuple iterator." )
11985 end
12086
121- column_types = TableTraits. column_types (iter)
122- column_names = TableTraits. column_names (iter)
87+ array_factory = if na_representation== :datavalue
88+ (t,rows) -> Array {t} (undef, rows)
89+ elseif na_representation== :missing
90+ (t,rows) -> begin
91+ if t <: DataValue
92+ return Array {Union{eltype(t),Missing}} (undef, rows)
93+ else
94+ return Array {t} (undef, rows)
95+ end
96+ end
97+ end
98+
99+ column_types = collect (T. parameters[2 ]. parameters)
100+ column_names = collect (T. parameters[1 ])
123101
124- rows = Base. iteratorsize (typeof (iter))== Base. HasLength () ? length (iter) : 0
102+ rows = Base. IteratorSize (typeof (iter))== Base. HasLength () ? length (iter) : 0
125103
126104 columns = []
127105 for (i, t) in enumerate (column_types)
@@ -132,10 +110,10 @@ function create_columns_from_iterabletable(source, sel_cols = :all; array_factor
132110 end
133111 end
134112
135- if Base. iteratorsize (typeof (iter))== Base. HasLength ()
136- _fill_cols_with_length ((columns... ), iter)
113+ if Base. IteratorSize (typeof (iter))== Base. HasLength ()
114+ _fill_cols_with_length ((columns... , ), iter)
137115 else
138- _fill_cols_without_length ((columns... ), iter)
116+ _fill_cols_without_length ((columns... , ), iter)
139117 end
140118
141119 if sel_cols == :all
0 commit comments