Brian1
June 20, 2022, 4:03am
1
Here I define a struct
struct Df{T,N} <: AbstractArray{T,N}
value::AbstractArray{T,N}
end
Base.size(df::Df)=size(df.value)
Base.getindex(df::Df,i...)=Df(df.value[i...])
Base.getindex(df::Df,i::Union{Int,CartesianIndex}...)=df.value[i...]
Base.eachindex(df::Df)=eachindex(df.value)
-> df=Df([[1,2,3] [2,3,4]])
3×2 Df{Int64, 2}:
1 2
2 3
3 4
Then, I can apply Base
operator ( like + -
) on df
-> df .+ 1
3×2 Matrix{Int64}:
2 3
3 4
4 5
But the result is a Matrix
rather than a Df
. The expected result would like:
-> df .+ 1
3×2 Df{Int64, 2}:
2 3
3 4
4 5
What am I missing here?
You need to define a few methods for broadcasting. The example at the end of Interfaces · The Julia Language is ver close to what you want.
1 Like
You’ll also need to implement the broadcasting API to preserve the matrix type: Interfaces · The Julia Language
Edit: what @skleinbo said
1 Like
DNF
June 20, 2022, 7:21am
4
Abstract field types are very bad for performance. It’s normally better to either just wrap Array{T, N}
or make the wrapped array type a type parameter for Df
.
1 Like
Brian1
June 20, 2022, 7:53am
6
Thanks for your advice. I have changed it to this:
struct Df{K,T,N,D,C} <: AbstractArray{T,N}
index::Vector{K}
value::C
column::D
Df{K,T,N,D,C}(index::Vector{K},value::AbstractArray{T,N},column::D=nothing) where {K,T,N,D,C}=
new{K,T,N,D,C}(index,value,column)
end
Would it be better, right?
Brian1
June 20, 2022, 8:08am
7
Yes, the example is very close. Thanks very much for your help.