What is the julia equivalent of np.indices in numpy? - julia

In Python, there is np.indices, which returns the indices of a grid:
Python 2.7.1
> import numpy as np
> x,y = np.indices((2,2))
> x
array([[0, 0],
[1, 1]])
> y
array([[0, 1],
[0, 1]])
What would be a similar function in Julia? Especially for multidimensional grids.
I tried eachindex, but it expects a grid as input, not just the dimensions. Also the output is a flat list of linear indices, instead of separated cartesian components.

It can be obtained using the CartesianIndices function:
julia> inds = CartesianIndices((2,2))
2×2 CartesianIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}:
CartesianIndex(1, 1) CartesianIndex(1, 2)
CartesianIndex(2, 1) CartesianIndex(2, 2)
julia> Tuple.(inds)
2×2 Array{Tuple{Int64,Int64},2}:
(1, 1) (1, 2)
(2, 1) (2, 2)
julia> getindex.(inds, 1)
2×2 Array{Int64,2}:
1 1
2 2
julia> getindex.(inds, 2)
2×2 Array{Int64,2}:
1 2
1 2

Related

Using Julia's dot notation and in place operation

How do I use both Julia's dot notation to do elementwise operations AND ensure that the result is saved in an already existing array?
function myfun(x, y)
return x + y
end
a = myfun(1, 2) # Results in a == 3
a = myfun.([1 2], [3; 4]) # Results in a == [4 5; 5 6]
function myfun!(x, y, out)
out .= x + y
end
a = zeros(2, 2)
myfun!.([1 2], [3; 4], a) # Results in a DimensionMismatch error
Also, does #. a = myfun([1 2], [3; 4]) write the result to a in the same way as I am trying to achieve with myfun!()? That is, does that line write the result directly to a without saving storing the result anywhere else first?
Your code should be:
julia> function myfun!(x, y, out)
out .= x .+ y
end
myfun! (generic function with 1 method)
julia> myfun!([1 2], [3; 4], a)
2×2 Matrix{Float64}:
4.0 5.0
5.0 6.0
julia> a
2×2 Matrix{Float64}:
4.0 5.0
5.0 6.0
As for #. a = myfun([1 2], [3; 4]) - the answer is yes, it does not create temporary arrays and operates in-place.
This isn't commonly required, and there are usually better ways to achieve this, but it's possible to broadcast on an output argument by using Reference values that point inside the output array.
julia> a = zeros(2, 2)
2×2 Matrix{Float64}:
0.0 0.0
0.0 0.0
julia> function myfun!(out, x, y)
out[] = x + y
end
myfun! (generic function with 1 method)
julia> myfun!.((Ref(a, i) for i in LinearIndices(a)), [1 2], [3; 4])
2×2 Matrix{Int64}:
4 5
5 6
julia> a
2×2 Matrix{Float64}:
4.0 5.0
5.0 6.0
Edit: Changed out to be the first parameter as per the Style guide - thanks to #phipsgabler for the reminder.

How do you access multi-dimension array by N array of index element-wise?

Suppose we have
A = [1 2; 3 4]
In numpy, the following syntax will produce
A[[1,2],[1,2]] = [1,4]
But, in julia, the following produce a permutation which output
A[[1,2],[1,2]] = [1 2; 3 4]
Is there a concise way to achieve the same thing as numpy without using for loops?
To get what you want I would use CartesianIndex like this:
julia> A[CartesianIndex.([(1,1), (2,2)])]
2-element Vector{Int64}:
1
4
or
julia> A[[CartesianIndex(1,1), CartesianIndex(2,2)]]
2-element Vector{Int64}:
1
4
Like Bogumil said, you probably want to use CartesianIndex. But if you want to get your result from supplying the vectors of indices for each dimensions, as in your Python [1,2],[1,2] example, you need to zip these indices first:
julia> A[CartesianIndex.(zip([1,2], [1,2]))]
2-element Vector{Int64}:
1
4
How does this work? zip traverses both vectors of indices at the same time (like a zipper) and returns an iterator over the tuples of indices:
julia> zip([1,2],[1,2]) # is a lazy iterator
zip([1, 2], [1, 2])
julia> collect(zip([1,2],[1,2])) # collect to show all the tuples
2-element Vector{Tuple{Int64, Int64}}:
(1, 1)
(2, 2)
and then CartesianIndex turns them into cartesian indices, which can then be used to get the corresponding values in A:
julia> CartesianIndex.(zip([1,2],[1,2]))
2-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 1)
CartesianIndex(2, 2)

indices of unique elements of vector in Julia

How to get indexes of unique elements of a vector?
For instance if you have a vector v = [1,2,1,3,5,3], the unique elements are [1,2,3,5] (output of unique) and their indexes are ind = [1,2,4,5]. What function allows me to compute ind so that v[ind] = unique(v) ?
This is a solution for Julia 0.7:
findfirst.(isequal.(unique(x)), [x])
or similar working under Julia 0.6.3 and Julia 0.7:
findfirst.(map(a -> (y -> isequal(a, y)), unique(x)), [x])
and a shorter version (but it will not work under Julia 0.7):
findfirst.([x], unique(x))
It will probably not be the fastest.
If you need speed you can write something like (should work both under Julia 0.7 and 0.6.3):
function uniqueidx(x::AbstractArray{T}) where T
uniqueset = Set{T}()
ex = eachindex(x)
idxs = Vector{eltype(ex)}()
for i in ex
xi = x[i]
if !(xi in uniqueset)
push!(idxs, i)
push!(uniqueset, xi)
end
end
idxs
end
Another suggestion is
unique(i -> x[i], 1:length(x))
which is about as fast as the function in the accepted answer (in Julia 1.1), but a bit briefer.
If you don't care about finding the first index for each unique element, then you can use a combination of the unique and indexin functions:
julia> indexin(unique(v), v)
4-element Array{Int64,1}:
3
2
6
5
Which gets one index for each unique element of v in v. These are all in base and works in 0.6. This is about 2.5 times slower than #Bogumil's function, but it's a simple alternative.
A mix between mattswon and Bogumił Kamiński answers (thanks !):
uniqueidx(v) = unique(i -> v[i], eachindex(v))
eachindex allows to work with any kind of array, even views.
julia> v = [1,2,1,3,5,3];
julia> uniqueidx(v)
4-element Vector{Int64}:
1
2
4
5
julia> v2 = reshape(v, 2, 3)
2×3 Matrix{Int64}:
1 1 5
2 3 3
julia> subv2 = view(v2, 1:2, 1:2)
2×2 view(::Matrix{Int64}, 1:2, 1:2) with eltype Int64:
1 1
2 3
julia> uniqueidx(subv2)
3-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 1)
CartesianIndex(2, 1)
CartesianIndex(2, 2)

Circular permutations

Given a vector z = [1, 2, 3], I want to create a vector of vectors with all circular permutations of z (i.e. zp = [[1,2,3], [3,1,2], [2,3,1]]).
I can print all elements of zp with
for i in 1:length(z)
push!(z, shift!(z)) |> println
end
How can I store the resulting permutations? Note that
zp = Vector(length(z))
for i in 1:length(z)
push!(z, shift!(z))
push!(zp, z)
end
doesn't work as it stores the same vector z 3 times in zp.
One way would just be to copy the vector before pushing it:
z = [1, 2, 3];
zp = Vector();
for i in 1:length(z)
push!(z, shift!(z))
push!(zp, copy(z))
end
gives me
julia> zp
3-element Array{Any,1}:
[2,3,1]
[3,1,2]
[1,2,3]
But I tend to prefer avoiding mutating operations when I can. So I'd instead write this as
julia> zp = [circshift(z, i) for i=1:length(z)]
3-element Array{Array{Int64,1},1}:
[3,1,2]
[2,3,1]
[1,2,3]
This seems to execute pretty quick on my machine (faster than a comprehension):
julia> z=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> zp=Vector{typeof(z)}(length(z))
3-element Array{Array{Int64,1},1}:
#undef
#undef
#undef
julia> for i=1:length(z)
zp[i]=circshift(z,i-1)
end
julia> zp
3-element Array{Array{Int64,1},1}:
[1,2,3]
[3,1,2]
[2,3,1]
julia>

How do I add a dimension to an array? (opposite of `squeeze`)

I can never remember how to do this this.
How can go
from a Vector (size (n1)) to a Column Matrix (size (n1,1))?
or from a Matrix (size (n1,n2)) to a Array{T,3} (size (n1,n2,1))?
or from a Array{T,3} (size (n1,n2,n3)) to a Array{T,4} (size (n1,n2,n3, 1))?
and so forth.
I want to know to take Array and use it to define a new Array with an extra singleton trailing dimension.
I.e. the opposite of squeeze
You can do this with reshape.
You could define a method for this:
add_dim(x::Array) = reshape(x, (size(x)...,1))
julia> add_dim([3;4])
2×1 Array{Int64,2}:
3
4
julia> add_dim([3;4])
2×1 Array{Int64,2}:
3
4
julia> add_dim([3 30;4 40])
2×2×1 Array{Int64,3}:
[:, :, 1] =
3 30
4 40
julia> add_dim(rand(4,3,2))
4×3×2×1 Array{Float64,4}:
[:, :, 1, 1] =
0.483307 0.826342 0.570934
0.134225 0.596728 0.332433
0.597895 0.298937 0.897801
0.926638 0.0872589 0.454238
[:, :, 2, 1] =
0.531954 0.239571 0.381628
0.589884 0.666565 0.676586
0.842381 0.474274 0.366049
0.409838 0.567561 0.509187
Another easy way other than reshaping to an exact shape, is to use cat and ndims together. This has the added benefit that you can specify "how many extra (singleton) dimensions you would like to add". e.g.
a = [1 2 3; 2 3 4];
cat(ndims(a) + 0, a) # add zero singleton dimensions (i.e. stays the same)
cat(ndims(a) + 1, a) # add one singleton dimension
cat(ndims(a) + 2, a) # add two singleton dimensions
etc.
UPDATE (julia 1.3). The syntax for cat has changed in julia 1.3 from cat(dims, A...) to cat(A...; dims=dims).
Therefore the above example would become:
a = [1 2 3; 2 3 4];
cat(a; dims = ndims(a) + 0 )
cat(a; dims = ndims(a) + 1 )
cat(a; dims = ndims(a) + 2 )
etc.
Obviously, like Dan points out below, this has the advantage that it's nice and clean, but it comes at the cost of allocation, so if speed is your top priority and you know what you're doing, then in-place reshape operations will be faster and are to be preferred.
Some time before the Julia 1.0 release a reshape(x, Val{N}) overload was added which for N > ndim(x) results in the adding of right most singleton dimensions.
So the following works:
julia> add_dim(x::Array{T, N}) where {T,N} = reshape(x, Val(N+1))
add_dim (generic function with 1 method)
julia> add_dim([3;4])
2×1 Array{Int64,2}:
3
4
julia> add_dim([3 30;4 40])
2×2×1 Array{Int64,3}:
[:, :, 1] =
3 30
4 40
julia> add_dim(rand(4,3,2))
4×3×2×1 Array{Float64,4}:
[:, :, 1, 1] =
0.0737563 0.224937 0.6996
0.523615 0.181508 0.903252
0.224004 0.583018 0.400629
0.882174 0.30746 0.176758
[:, :, 2, 1] =
0.694545 0.164272 0.537413
0.221654 0.202876 0.219014
0.418148 0.0637024 0.951688
0.254818 0.624516 0.935076
Try this
function extend_dims(A,which_dim)
s = [size(A)...]
insert!(s,which_dim,1)
return reshape(A, s...)
end
the variable extend_dim specifies which dimension to extend
Thus
extend_dims(randn(3,3),1)
will produce a 1 x 3 x 3 array and so on.
I find this utility helpful when passing data into convolutional neural networks.

Resources