Modifying Objects
DimensionalData.jl objects are all struct
rather than mutable struct
. The only things you can modify in-place are the values of the contained arrays or metadata Dict
s if they exist.
Everything else must be rebuilt and assigned to a variable.
modify
Modify the inner arrays of a AbstractDimArray
or AbstractDimStack
, with modify
. This can be useful to e.g. replace all arrays with CuArray
moving the data to the GPU, collect
all inner arrays to Array
without losing the outer DimArray
wrappers, and similar things.
julia> using DimensionalData
julia> A = falses(X(3), Y(5))
╭──────────────────────╮
│ 3×5 DimArray{Bool,2} │
├──────────────────────┴─────────────────────────────────── dims ┐
↓ X, → Y
└────────────────────────────────────────────────────────────────┘
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
julia> parent(A)
3×5 BitMatrix:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
julia> A_mod = modify(Array, A)
╭──────────────────────╮
│ 3×5 DimArray{Bool,2} │
├──────────────────────┴─────────────────────────────────── dims ┐
↓ X, → Y
└────────────────────────────────────────────────────────────────┘
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
julia> parent(A_mod)
3×5 Matrix{Bool}:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
reorder
reorder
is like reverse but declarative, rather than imperative: we tell it how we want the object to be, not what to do.
Reorder a specific dimension
julia> using DimensionalData.Lookups;
julia> A = rand(X(1.0:3.0), Y('a':'n'));
julia> reorder(A, X => ReverseOrdered())
╭──────────────────────────╮
│ 3×14 DimArray{Float64,2} │
├──────────────────────────┴───────────────────────────────────────────── dims ┐
↓ X Sampled{Float64} 3.0:-1.0:1.0 ReverseOrdered Regular Points,
→ Y Categorical{Char} 'a':1:'n' ForwardOrdered
└──────────────────────────────────────────────────────────────────────────────┘
↓ → 'a' 'b' 'c' … 'l' 'm' 'n'
3.0 0.884218 0.686915 0.208271 0.744517 0.487197 0.86789
2.0 0.903705 0.0915867 0.247032 0.824556 0.298728 0.933212
1.0 0.159092 0.193627 0.317813 0.474755 0.474052 0.364844
mergedims
mergedims
is like reshape
, but simultaneously merges multiple dimensions into a single combined dimension with a lookup holding Tuples
of the values of both dimensions.
rebuild
rebuild
is one of the core functions of DimensionalData.jl. Basically everything uses it somewhere. And you can too, with a few caveats.
Warning
rebuild
assumes you know what you are doing. You can quite easily set values to things that don't make sense. The constructor may check a few things, like the number of dimensions matches the axes of the array. But not much else.
julia> A1 = rebuild(A; name=:my_array)
╭───────────────────────────────────╮
│ 3×14 DimArray{Float64,2} my_array │
├───────────────────────────────────┴──────────────────────────────────── dims ┐
↓ X Sampled{Float64} 1.0:1.0:3.0 ForwardOrdered Regular Points,
→ Y Categorical{Char} 'a':1:'n' ForwardOrdered
└──────────────────────────────────────────────────────────────────────────────┘
↓ → 'a' 'b' 'c' … 'l' 'm' 'n'
1.0 0.159092 0.193627 0.317813 0.474755 0.474052 0.364844
2.0 0.903705 0.0915867 0.247032 0.824556 0.298728 0.933212
3.0 0.884218 0.686915 0.208271 0.744517 0.487197 0.86789
julia> name(A1)
:my_array
The most common use internally is the arg version on Dimension
. This is very useful in dimension-based algorithms as a way to transform a dimension wrapper from one object to another:
julia> d = X(1)
X 1
julia> rebuild(d, 1:10)
X 1:10
rebuild
applications are listed here. AbstractDimArray
and AbstractDimStack
always accept these keywords or arguments, but those in [ ] brackets may be thrown away if not needed. Keywords in ( ) will error if used where they are not accepted.
Type | Keywords | Arguments |
---|---|---|
AbstractDimArray | data , dims , [refdims , name , metadata ] | as with kw, in order |
AbstractDimStack | data , dims , [refdims ], layerdims , [metadata , layermetadata ] | as with kw, in order |
Dimension | val | val |
Selector | val , (atol ) | val |
Lookup | data , (order , span , sampling , metadata ) | keywords only |
rebuild
magic
rebuild
with keywords will even work on objects DD doesn't know about!
julia> nt = (a = 1, b = 2)
(a = 1, b = 2)
julia> rebuild(nt, a = 99)
(a = 99, b = 2)
Really, the keyword version is just ConstructionBase.setproperties
underneath, but wrapped so objects can customise the DD interface without changing the more generic ConstructionBase.jl behaviours and breaking e.g. Accessors.jl in the process.
set
set
gives us a way to set the values of the immutable objects in DD, like Dimension
and LookupArray
. Unlike rebuild
it tries its best to do the right thing. You don't have to specify what field you want to set. Just pass in the object you want to be part of the lookup. Usually, there is no possible ambiguity.
set
is still improving. Sometimes it may not do the right thing. If you think this is the case, create a GitHub issue.
julia> set(A, Y => Z)
╭──────────────────────────╮
│ 3×14 DimArray{Float64,2} │
├──────────────────────────┴───────────────────────────────────────────── dims ┐
↓ X Sampled{Float64} 1.0:1.0:3.0 ForwardOrdered Regular Points,
→ Z Categorical{Char} 'a':1:'n' ForwardOrdered
└──────────────────────────────────────────────────────────────────────────────┘
↓ → 'a' 'b' 'c' … 'l' 'm' 'n'
1.0 0.159092 0.193627 0.317813 0.474755 0.474052 0.364844
2.0 0.903705 0.0915867 0.247032 0.824556 0.298728 0.933212
3.0 0.884218 0.686915 0.208271 0.744517 0.487197 0.86789