Julia Reverse N-dimensional arrays - arrays

In Python, Numpy arrays can be reversed using the standard [::-1] i.e.
A = np.diag(np.arange(1,3))
A[::, ::-1]
A[::-1]
A[::-1, ::-1]
Julia does not support [::-1] and the reverse method only works on 1D arrays and only 1D columns (where as rows are 2D by default).
Is there an alternative I'm missing?

Try the following, which is essentially the same as the numpy version:
julia> X = rand(3,3)
3x3 Array{Float64,2}:
0.782622 0.996359 0.335781
0.719058 0.188848 0.985693
0.455355 0.910717 0.870187
julia> X[end:-1:1,end:-1:1]
3x3 Array{Float64,2}:
0.870187 0.910717 0.455355
0.985693 0.188848 0.719058
0.335781 0.996359 0.782622

In Julia 1.0, to reverse a (column) vector:
julia> reverse([1, 2, 3])
3-element Array{Int64,1}:
3
2
1
For reversing rows, just state that you want to flip the second dimension:
julia> reverse([1 2 3], dims=2)
1×3 Array{Int64,2}:
3 2 1
EDIT: Alternatively, you can also index in reverse using end:-1:1, and that way also allows you to request a view instead of a copy:
julia> a = reshape(randperm(9), 3, 3)
3×3 Matrix{Int64}:
4 7 9
5 2 1
3 6 8
julia> #view a[:, end:-1:1]
3×3 view(::Matrix{Int64}, :, 3:-1:1) with eltype Int64:
9 7 4
1 2 5
8 6 3

Following up #IainDunning's answer, an important difference between numpy and Julia here is that X[:,end:-1:1] in Julia returns a copy and in numpy X[:,::-1] will return a view of the same data (no copy is made).
I'm just learning Julia myself, but it seems like you can accomplish something similar in Julia using sub(X, :, size(X)[2]:-1:1), which returns Julia's equivalent of a view (SubArray). Interestingly, you can't use the end keyword in this construct as far as I can see, and instead you must pass in the actual end index in the dimension.

You can use the function flipdim(mat, d).
Ref: http://docs.julialang.org/en/release-0.4/stdlib/arrays/

Try this set of functions:
function reverser(x::AbstractArray, dims::AbstractVector{<:Integer})
y = copy(x)
for d in dims
y = reverse(y, dims=d)
end
return y
end
reverser(x::AbstractArray) = reverser(x, 1:ndims(x)) # all dimensions
reverser(x::AbstractArray, d::Integer) = reverser(x, [1])

Julia 1.6 supports reversing any or all of the dimensions of an arbitrary multidimensional array (implemented here). To reverse all of the dimensions, you can simply do reverse(X).

Related

Julia accessing specific Matrix elements using vectors as indexes

Suppose I have a 4*2 matrix as follows:
a = [1 2; 3 4; 5 6; 7 8]
4×2 Matrix{Int64}:
1 2
3 4
5 6
7 8
I want to access the matrix using a vector specifying which element I want to access in each column. In NumPy from python, I would do the following command:
a[[1,3], [1,2]]
# expected output:
1×2 Matrix{Int64}:
1(as a[1,1]) 6(as a[3,2])
but in Julia, I got the following matrix:
2×2 Matrix{Int64}:
1 2
5 6
How can I do it in an julia way?
UPDATE: Inspired by DNF answer:
julia> a[CartesianIndex.([1 3], [1 2])]
1×2 Matrix{Int64}:
1 6
seems to me the right balance of clarity and similarity to OP.
ORIGINAL answer:
Maybe not the optimal way, but:
[a[x...] for x in [[[1,1]] [[3,2]]]]
works.
Note that this returns a row vector, like in the OP. In Julia there is a difference between a vector and a matrix. A matrix with one row or one column is not the same as a vector.
The [[]] notation is to let hcat handle vector elements correctly. If a vector output is good enough, then: [[1,1],[3,2]] is enough.
The syntax a[i, j] is syntax sugar for getindex(a, i, j). You can broadcast getindex to get the desired behavior (unfortunately, you cannot broadcast the [] syntax itself):
getindex.(Ref(a), [1,3], [1,2])
You must protect a itself against being broadcasted, by wrapping it in a Ref.

How to convert an array of array to array in Julia?

In the following example I am getting an array of array as an output. I would like to seek suggestion on reducing it to n-element vector.
Example: I have a vector x and then I perform subtraction on first 2 elements of the array which outputs a.
x = Float64.([1,2,3,4,5])
a= x[2,:] - x[1,:]
1-element Vector{Float64}:
1.0
Now when i collect the following range, it returns array of array, as shown below.
c = collect(range(minimum(x).*a, maximum(x).*a, length=10))
10-element Vector{Vector{Float64}}:
[1.0]
[1.4444444444444444]
[1.8888888888888888]
[2.333333333333333]
[2.7777777777777777]
[3.2222222222222223]
[3.6666666666666665]
[4.111111111111111]
[4.555555555555555]
[5.0]
I would like to know how may I convert this to a vector, which can output following result?
# Expected result:
10-element Vector{Float64}:
1.0
1.4444444444444444
1.8888888888888888
2.333333333333333
2.7777777777777777
3.2222222222222223
3.6666666666666665
4.111111111111111
4.555555555555555
5.0
Thanks!!
When constructing a you want a= x[2] - x[1]. Then a will be a scalar, and everything else will behave as expected.
In general, you can use a combination of splatting and vcat:
julia> xs = [[1],[2,3],[],[4],[5,6,7]]
5-element Vector{Vector{Any}}:
[1]
[2, 3]
[]
[4]
[5, 6, 7]
julia> vcat(xs...)
7-element Vector{Any}:
1
2
3
4
5
6
7
That being said, I would follow Oscar Smith's advice and fix the root problem.

Vectorized multiplication: Multiply two vectors in Julia, element-wise

I decided to dive into Julia and hitting the wall; fast.
I am trying to replicate a simple operation, which would like as follows in python numpy
a = numpy.array([1,2,3])
b = numpy.array([1,2,3])
a*b
[output]: [1,4,9]
In other words "[1,4,9]" is the output I expect.
I tried in Julia the following:
a = [1,2,3]
b = [1,2,3]
a*b
[output]: MethodError: no method matching *(::Array{Int64,1}, ::Array{Int64,1})
or after trying to wise up:
a = [1,2,3]
b = [1,2,3]'
a*b
[output]: 3×3 Array{Int64,2}:
1 2 3
2 4 6
3 6 9
I am aware that this seems like a basic question, but my Googling does not seem my finest today and/or stackoverflow could use this question & answer ;)
Thanks for any help and pointers!
Best
Julia needs a . in front of the operator or function call to indicate you want elementwise multiplication and not an operation on the vector as a unit. This is called broadcasting the array:
julia> a = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> b = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> a .* b
3-element Array{Int64,1}:
1
4
9
I just found a solution, although surely not optimal as it will generate a dot product and then select the diagonals.... to much calc!\
use LinearAlgebra
a = [1,2,3]
b = [1,2,3]
c = a * b'
diag(c)
I am pretty sure that there is a better solution.

Accessing elements of array based on indices given by another array

Suppose I have the following 4x4 Array in Julia:
julia> A=rand(4,4)
4×4 Array{Float64,2}:
0.00624508 0.624399 0.458094 0.341848
0.303817 0.269487 0.580949 0.534655
0.748525 0.419411 0.469938 0.659914
0.730659 0.191461 0.996144 0.74772
And I have another 6x2 Array where each row represents a row-column pair:
julia> B=[ 1 1; 1 3; 2 2; 2 4; 3 1; 3 3]
6×2 Array{Int64,2}:
1 1
1 3
2 2
2 4
3 1
3 3
The first row of B represents the element [1,1] of A, the second row of B represents the element [1,3] of A, and so on. I want to access the elements of A based on the coordinates given by each row of B. In R for example, the command A[B] gives exactly what I want: 0.00624508 0.458094 0.269487 0.534655 0.748525 0.469938 but in Julia, the same command gives
julia> A[B]
6×2 Array{Float64,2}:
0.00624508 0.00624508
0.00624508 0.748525
0.303817 0.303817
0.303817 0.730659
0.748525 0.00624508
0.748525 0.748525
and this is not what I want. Is there a similar way of coding A[B] in Julia, so that I obtain what I obtain in R? Must be applicable to any Array.
Construct an array of CartesianIndex out of your index pairs:
julia> A[CartesianIndex.(B[:, 1], B[:, 2])]
6-element Array{Float64,1}:
0.987200021334854
0.5261639427155012
0.8430528192705655
0.5300778835366697
0.5044387593056074
0.0025132074927423087
This is necessary to distinguish such "point indexing" from "shape indexing", as you observed it (I made those terms up).
Ideally, you would already construct B as such an array, but that is not always feasible, of course.

The best way to convert Vector into Matrix in Julia?

Suppose I have a variable v of a type Vector.
What would be the best / fastest way to just convert it into Matrix representation (for whatever reason)?
To clarify, v'' will do the job, but is it the best way to do this?
Reshape should be the most efficient. From the docs:
reshape(A, dims): Create an array with the same data as the given array, but with different dimensions. An implementation for a particular type of array may choose whether the data is copied or shared.
julia> v = rand(3)
3-element Array{Float64,1}:
0.690673
0.392635
0.0519467
julia> reshape(v, length(v), 1)
3x1 Array{Float64,2}:
0.690673
0.392635
0.0519467
v[:,:] is probably the clearest way to do this.
For example:
julia> v=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> m=v[:,:]
3x1 Array{Int64,2}:
1
2
3
julia> ndims(m)
2
Or just use:
v = [1, 2, 3]
hcat(v)
Result:
3×1 Array{Int64,2}:
1
2
3

Resources