Skip to content

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 Dicts 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
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
julia> parent(A)
3×5 BitMatrix:
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
julia
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
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
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
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
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
julia> d = X(1)
X 1
julia
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.

TypeKeywordsArguments
AbstractDimArraydata, dims, [refdims, name, metadata]as with kw, in order
AbstractDimStackdata, dims, [refdims], layerdims, [metadata, layermetadata]as with kw, in order
Dimensionvalval
Selectorval, (atol)val
Lookupdata, (order, span, sampling, metadata)keywords only

rebuild magic

rebuild with keywords will even work on objects DD doesn't know about!

julia
julia> nt = (a = 1, b = 2)
(a = 1, b = 2)
julia
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
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