AxisKeys.jl icon indicating copy to clipboard operation
AxisKeys.jl copied to clipboard

Cannot create KeyedArray from some tables

Open aplavin opened this issue 4 years ago • 1 comments

Docs for wrapdims say

wrapdims(table, value, names...; default=undef, sort=false, force=false) Construct KeyedArray(NamedDimsArray(A,names),keys) from a table matching the Tables.jl API. (It must support both Tables.columns and Tables.rows.) The contents of the array is taken from the column value::Symbol of the table. Each symbol in names specifies a column whose unique entries become the keys along a dimenension of the array.

It works with the most basic column-table:

julia> wrapdims((a=[1, 2], b=[2, 1]), :a, :b)
1-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓   b ∈ 2-element Vector{Int64}
And data, 2-element Vector{Int64}:
 (2)  1
 (1)  2

but not with a rowtable - an exception gets thrown:

julia> wrapdims([(a=1, b=2), (a=2, b=1)], :a, :b)
ERROR: ArgumentError: wrong number of names, got (:a, :b) with ndims(A) == 1
Stacktrace:
 [1] check_names(A::Vector{NamedTuple{(:a, :b), Tuple{Int64, Int64}}}, names::Tuple{Symbol, Symbol})
   @ AxisKeys ~/.julia/packages/AxisKeys/KCixh/src/wrap.jl:105
 [2] wrapdims(A::Vector{NamedTuple{(:a, :b), Tuple{Int64, Int64}}}, n::Symbol, names::Symbol)
   @ AxisKeys ~/.julia/packages/AxisKeys/KCixh/src/wrap.jl:87

Looks like a wrong method gets dispatched: https://github.com/mcabbott/AxisKeys.jl/blob/master/src/wrap.jl#L87 instead of https://github.com/mcabbott/AxisKeys.jl/blob/master/src/tables.jl#L213.

aplavin avatar Nov 14 '21 08:11 aplavin

That's unfortunate, I guess it's an argument for not using the same function to construct from an array and from a Table. We did not think of this problem when adding the feature, in https://github.com/mcabbott/AxisKeys.jl/pull/21, although we did think that wrapdims is a weird function that should perhaps be re-organised.

The short-term hack is of course to call the inner function yourself:

julia> AxisKeys._wrap_table(KeyedArray, identity, [(a=1, b=2.2), (a=10, b=22.0)], :a, :b)
1-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓   b ∈ 2-element Vector{Float64}
And data, 2-element Vector{Int64}:
  (2.2)   1
 (22.0)  10

julia> wrapdims([(a=1, b=2.2), (a=10, b=22.0)], :c)
2-element NamedDimsArray(::Vector{NamedTuple{(:a, :b), Tuple{Int64, Float64}}}, (:c,)):
↓ c  (a = 1, b = 2.2)
     (a = 10, b = 22.0)

mcabbott avatar Nov 14 '21 15:11 mcabbott