TypedTables.jl
TypedTables.jl copied to clipboard
additional row-based creators
i can submit a PR if you like this API:
julia> using TypedTables
julia> function Base.push!(t::Table{<:NamedTuple}, v::Tuple)
map(push!, columns(t), v)
return t
end
julia> Table(names::Tuple, types::Tuple, args...) =
TypedTables.Table(NamedTuple{names}(tuple(map((t,a)->t[a...], types, zip(args...))...)))
Table
julia> Table((:name,:age),(String,Int),
("Alice",25),
("Bob",42),
("Charlie",37))
Table with 2 columns and 3 rows:
name age
┌─────────────
1 │ Alice 25
2 │ Bob 42
3 │ Charlie 37
julia> push!(ans, ("Doris",62))
Table with 2 columns and 4 rows:
name age
┌─────────────
1 │ Alice 25
2 │ Bob 42
3 │ Charlie 37
4 │ Doris 62
this is even better for me:
julia> function Table(kind::Tuple, args...)
names, types = collect(zip(kind...))
TypedTables.Table(NamedTuple{names}(tuple(map((t,a)->t[a...], types, zip(args...))...)))
end
Table (generic function with 1 method)
julia> Table(((:name,String), (:age,Int)),
("Alice",25),
("Bob",42),
("Charlie",37))
Table with 2 columns and 3 rows:
name age
┌─────────────
1 │ Alice 25
2 │ Bob 42
3 │ Charlie 37
Eventually some more constructors would be excellent. Thanks for brainstorming.
Thinking aloud, I think Julia 1.1 might let us do Table(name = String, age = Int) to make an empty table easily and in an inferrible way. But you can just do Table(name = String[], age = Int[]), and this is way clearer and more explicit.
Using splatting and collect and so-on is a bit slow, you’re probably just as wel putting [ and ] around args. At which point you’re closer to a constructor that already works.
But around all of this, we are inheriting AbstractArray and all of it’s usual conventions and constructor expectations. Like the usage of convert to insert elements... are there any conversions defined between tuples and named tuples?
Finally - I’m curious how you ended up with all your data as tuples in the first place?
that collect is not necessary, good catch.
it's not that all my data are tuples, but rather that sometimes it's easier to deal with rows as the logical units instead of columns.
say for example you had a table with 1000 rows, and you wanted to insert another (or change one) in the middle. say bob's age is really 43, and his entry is at row 658. as it stands now, you'd have to painstakingly make sure that you inserted the new values at the same position in each column. good chance you might actually change charlie's age at row 659. much less likely to make a mistake when dealing with a vector of tuples.