ShiftedArrays
Implementation of shifted arrays.
Shifted Arrays
A ShiftedArray
is a lazy view of an Array, shifted on some or all of its indexing dimensions by some constant values.
julia> v = reshape(1:16, 4, 4)
4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
julia> s = ShiftedArray(v, (2, 0))
4×4 ShiftedArray{Int64, Missing, 2, Base.ReshapedArray{Int64, 2, UnitRange{Int64}, Tuple{}}}:
missing missing missing missing
missing missing missing missing
1 5 9 13
2 6 10 14
The parent Array as well as the amount of shifting can be recovered with parent
and shifts
respectively.
julia> parent(s)
4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
julia> shifts(s)
(2, 0)
shifts
returns a Tuple
, where the n-th element corresponds to the shift on the n-th dimension of the parent Array
.
Use copy
to collect the shifted data into an Array
:
julia> copy(s)
4×4 Matrix{Union{Missing, Int64}}:
missing missing missing missing
missing missing missing missing
1 5 9 13
2 6 10 14
If you pass an integer, it will shift in the first dimension:
julia> ShiftedArray(v, 1)
4×4 ShiftedArray{Int64, Missing, 2, Base.ReshapedArray{Int64, 2, UnitRange{Int64}, Tuple{}}}:
missing missing missing missing
1 5 9 13
2 6 10 14
3 7 11 15
A custom default value (other than missing
) can be provided with the default
keyword:
julia> ShiftedArray([1.2, 3.1, 4.5], 1, default = NaN)
3-element ShiftedVector{Float64, Float64, Vector{Float64}}:
NaN
1.2
3.1
Out of bound indexes
Accessing indexes outside the ShiftedArray
give a BoundsError
, even if the shifted index would have been valid in the parent array.
julia> ShiftedArray([1, 2, 3], 1)[4]
ERROR: BoundsError: attempt to access 3-element ShiftedVector{Int64, Missing, Vector{Int64}} at index [4]
Shifting the data
Using the ShiftedArray
type, this package provides two operations for lazily shifting vectors: lag
and lead
.
julia> v = [1, 3, 5, 4];
julia> ShiftedArrays.lag(v)
4-element ShiftedVector{Int64, Missing, Vector{Int64}}:
missing
1
3
5
julia> v .- ShiftedArrays.lag(v) # compute difference from previous element without unnecessary allocations
4-element Vector{Union{Missing, Int64}}:
missing
2
2
-1
julia> s = ShiftedArrays.lag(v, 2) # shift by more than one element
4-element ShiftedVector{Int64, Missing, Vector{Int64}}:
missing
missing
1
3
lead
is the analogous of lag
but shifts in the opposite direction:
julia> v = [1, 3, 5, 4];
julia> ShiftedArrays.lead(v)
4-element ShiftedVector{Int64, Missing, Vector{Int64}}:
3
5
4
missing
Shifting the data circularly
Julia Base provides a function circshift
to shift the data circularly. However this function creates a copy of the vector, which may be unnecessary if the rotated vector is to be used only once. This package provides the CircShiftedArray
type, which is a lazy view of an array shifted on some or all of his indexing dimensions by some constant values.
Our implementation of circshift
relies on them to avoid copying:
julia> w = reshape(1:16, 4, 4);
julia> s = ShiftedArrays.circshift(w, (1, -1))
4×4 CircShiftedArray{Int64, 2, Base.ReshapedArray{Int64, 2, UnitRange{Int64}, Tuple{}}}:
8 12 16 4
5 9 13 1
6 10 14 2
7 11 15 3
As usual, you can copy
the result to have a normal Array
:
julia> copy(s)
4×4 Matrix{Int64}:
8 12 16 4
5 9 13 1
6 10 14 2
7 11 15 3