Vector of matrices in Julia - julia

How can I make a vector of (non-sparse) matrices in Julia? Then I want to use push! to add elements to that.
So if the name of the vector is V, then V[1] will be a matrix or Array{Float64,2}.
I know this works if the elements of the vector are sparse:
V = Array(SparseMatrixCSC).

You can use the Matrix alias (Array{T, 2}):
julia> v = Matrix{Float64}[]
0-element Array{Array{Float64,2},1}
julia> x = rand(2, 2)
2×2 Array{Float64,2}:
0.0877254 0.256971
0.719441 0.653947
julia> push!(v, x)
1-element Array{Array{Float64,2},1}:
[0.0877254 0.256971; 0.719441 0.653947]
julia> v[1]
2×2 Array{Float64,2}:
0.0877254 0.256971
0.719441 0.653947

I just tried this and it worked:
V = Array(Array{Float64,2}, 0);
edit: As #pkofod suggested, this way is prefered:
T = Array{Float64,2};
V = Array{T}(0)
other options: V = Array{Float64,2}[ ] or V = Matrix{Float64}[ ]

Related

Julia - Equivalent of python `pop`. Remove elements from array using boolean array and return them

Is there an equivalent to Python's pop? I have an array x and a boolean array flag of the same length. I would like to extract x[flag] and be able to store it in a variable x_flagged while at the same time remove them in place from x.
x = rand(1:5, 100)
flag = x .> 2
x_flagged = some_function!(x, flag) # Now x would be equal to x[x .<= 2]
Try this one using deleteat!
julia> function pop_r!(list, y) t = list[y]; deleteat!( list, y ); t end
julia> x = rand(1:5, 100)
100-element Vector{Int64}
julia> flag = x .> 2
100-element BitVector
julia> pop_r!( x, flag )
60-element Vector{Int64}
julia> x
40-element Vector{Int64}
You can use splice! with a bit of help from findall:
julia> x_flagged = splice!(x, findall(flag))
59-element Vector{Int64}:
...
julia> size(x)
(41,)
splice!(a::Vector, indices, [replacement]) -> items
Remove items at specified indices, and return a collection containing the removed items.

How to iterate over two arrays in parallel

I have two arrays that I want to iterate over at the same time.
I'm using this:
julia> xs = [1,2,3];
julia> ys = [4,5,6];
julia> for i in 1:length(xs)
x = xs[i]
y = ys[i]
#show x, y
end
(x, y) = (1, 4)
(x, y) = (2, 5)
(x, y) = (3, 6)
Is there a better way to iterate over multiple arrays in Julia?
Use zip along with tuple destructuring:
julia> xs = [1,2,3];
julia> ys = [4,5,6];
julia> for (x, y) in zip(xs, ys)
#show x, y
end
(x, y) = (1, 4)
(x, y) = (2, 5)
(x, y) = (3, 6)
zip will stop iteration at the shortest array:
julia> for (x, y) in zip([1,2], [0,0,0])
#show x, y
end
(x, y) = (1, 0)
(x, y) = (2, 0)
This pattern can be generalized to an arbitrary number of lists:
julia> for (x, y, z) in zip([1,2], [3,4], [5,6])
#show x, y, z
end
(x, y, z) = (1, 3, 5)
(x, y, z) = (2, 4, 6)
One possibility consists in using the eachindex function: if it is given multiple Array-like arguments, it will return a iterable set of indices suitable to iterate on all arguments at once.
This is useful in particular in the following situations:
when you need to use the index itself (for example because you don't only need to access the elements of the collections, but also set some of them), or
when you want to check that both arrays indeed have the same number of elements (this might or might not be a desired property depending on your use case).
Example 1: using the index itself to fill the first array with values coming from the second
julia> x = [1,2,3];
julia> y = [4,5,6];
julia> #inbounds for i in eachindex(x, y)
x[i] = 2*y[i]
end
julia> x
3-element Array{Int64,1}:
8
10
12
Example 2: check that the arrays have the same range
julia> x = [1,2];
julia> y = [4,5,6];
julia> #inbounds for i in eachindex(x, y)
x[i] = 2*y[i]
end
ERROR: DimensionMismatch("all inputs to eachindex must have the same indices, got [1, 2] and [1, 2, 3]")
Example 3: note that eachindex generalizes well for multi-dimensional arrays too.
julia> x = zeros(2, 3);
julia> y = ones(2, 3);
julia> #inbounds for i in eachindex(x, y)
x[i] = 2*y[i]
end
julia> x
2×3 Array{Float64,2}:
2.0 2.0 2.0
2.0 2.0 2.0
You can iterate over multiple collections using map and foreach. For example, with map:
julia> x, y = 1:3, 4:6;
julia> map(hypot, x, y)
3-element Array{Float64,1}:
4.123105625617661
5.385164807134504
6.708203932499369
For more complicated multi-line anonymous functions, you can use do-block syntax:
julia> xs, ys = 1:4, 10:10:40;
julia> map(xs, ys) do x, y
if isodd(x)
x + y
else
x * y
end
end
4-element Array{Int64,1}:
11
40
33
160
foreach is very similar to map, but is intended for use when a function is applied for its side effect, like printing or plotting, rather than its return value. An example with foreach:
julia> x, y = ["a", "b", "c"], 1:3;
julia> foreach(println ∘ ^, x, y)
a
bb
ccc
Note the use of the function composition operator in the foreach call.

Creating matrix of draws from vector of distributions

I have a vector of n distributions and I am trying to create a n x t matrix of t draws from each of the n distributions.
using Distributions
d = [Uniform(0,1), Uniform(1,2), Uniform(3,4)]
r = [rand(i, 2) for i in d] # Want a 3x2 matrix, but get an array of arrays
Expected:
[0.674744 0.781853; 1.70171 1.56444; 3.65103 3.76522]
Actual:
[[0.674744, 0.781853], [1.70171, 1.56444], [3.65103, 3.76522]]
Try double indexing of a comprehension:
julia> using Distributions
julia> d = [Uniform(0,1), Uniform(1,2), Uniform(3,4)]
3-element Array{Uniform{Float64},1}:
Uniform{Float64}(a=0.0, b=1.0)
Uniform{Float64}(a=1.0, b=2.0)
Uniform{Float64}(a=3.0, b=4.0)
julia> r = [rand(i) for i in d, _ in 1:2]
3×2 Array{Float64,2}:
0.687725 0.433771
1.28782 1.00533
3.37017 3.88304
Another interesting option is to use broadcasting assignment:
julia> out = Matrix{Float64}(undef, 3, 2)
3×2 Array{Float64,2}:
1.0735e-313 7.30082e-316
7.30082e-316 7.30082e-316
7.30082e-316 6.11918e-316
julia> out .= rand.(d)
3×2 Array{Float64,2}:
0.803554 0.457955
1.4354 1.41107
3.31749 3.2684
This is shorter and might be useful if you need to sample many times and want an in-place operation (which is often the case in simulation modeling).

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>

Resources