AxisKeys.jl
AxisKeys.jl copied to clipboard
Unable to use Tuples to label a KeyedArray
Trying to construct an array where the labels are stored in a tuple throws an error:
MethodError: no method matching axes(::Tuple{Symbol, Symbol, Symbol}, ::Int64)
Closest candidates are:
axes(::Tuple) at tuple.jl:28
axes(::TArray, ::Any...) at /home/lime/.julia/packages/Libtask/RQkfZ/src/tarray.jl:198
axes(::DataFrames.GroupKey, ::Integer) at /home/lime/.julia/packages/DataFrames/vuMM8/src/groupeddataframe/groupeddataframe.jl:517
The code that generated this error --
table = KeyedArray(data; model=model_names, statistic=(:cv_diff, :se_cv_diff, :weight))
I'm guessing this is unintended, and the method is accidentally overtyped. If it's intentional, KeyedArray should probably be typed in such a way as to to avoid passing a tuple in the first place
It does assume they are AbstractVectors; I see that the name-less constructor has an explicit check:
julia> table = KeyedArray(rand(3,3), ([1,2,3], (:cv_diff, :se_cv_diff, :weight)))
ERROR: ArgumentError: key vectors must all be AbstractVectors
Stacktrace:
[1] construction_check(data::Matrix{Float64}, keys::Tuple{Vector{Int64}, Tuple{Symbol, Symbol, Symbol}})
@ AxisKeys ~/.julia/dev/AxisKeys/src/struct.jl:28
[2] KeyedArray(data::Matrix{Float64}, keys::Tuple{Vector{Int64}, Tuple{Symbol, Symbol, Symbol}})
@ AxisKeys ~/.julia/dev/AxisKeys/src/struct.jl:13
The reason for this is that it wants to allow OffsetArrays, for which it needs always to think about axes not size, and Tuples have only the latter. It's possible that this could be worked around, but I'm not sure how much work it would be.
The named constructor accepts any number of keywords, and I didn't think you could also impose a type constraint:
julia> @less KeyedArray(rand(3,3); model=[1,2,3], statistic=(:cv_diff, :se_cv_diff, :weight))
julia> f1(; kw...) = kw;
julia> f1(; a=1, b=2)
pairs(::NamedTuple) with 2 entries:
:a => 1
:b => 2
julia> f2(; kw::Int...) = kw;
ERROR: syntax: "kw::Int" is not a valid function argument name around REPL[163]:1
It could perhaps be arranged that this hit the construction_check error first, though.
@mcabbott I would think you could replace the types in the constructor that say AbstractVector with AbstractVecOrTuple, then just insert this at the top of the constructor:
for kwarg in kwargs
if kwarg isa Tuple
kwarg = [kwarg[i] for i in length(kwarg)]
end
end
Which will convert the tuples to vectors.