Creating matrix of draws from vector of distributions - julia

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).

Related

How to calculate Euclidean distance between a tuple and each tuple in a Vector using map in Julia?

I want to calculate the Euclidean distance between a tuple and each tuple within a Vector in Julia using the map function, like below (but I get two values instead of three):
julia> tups = [
(1, 3),
(11, 2),
(0, 1)
];
julia> map((x, y) -> √(sum((x.-y).^2)), tups, (3, 3))
2-element Vector{Float64}:
2.0
8.06225774829855
How can I make it work correctly?
Julia has the Distances package especially for these types of calculations. The 'Julian way' encourages interoperability between packages to allow benefitting from future development of the ecosystem. For example, new metric definitions, or specialized hardware code to compute distances.
For the problem in the post, the code would look:
julia> using Distances
julia> tups = [
(1, 3),
(11, 2),
(0, 1)
];
julia> euclidean.(tups,Ref((3,3)))
3-element Vector{Float64}:
2.0
8.06225774829855
3.605551275463989
Notice the use of broadcasting instead of map with dot syntax euclidean.. The Ref((3,3)) causes broadcasting to consider (3,3) as a single element to broadcast and not break it to a pair of Ints.
The code you've written is pretty equal to this:
[
func((1, 3), 3),
func((11, 2), 3)
]
The map function iterates over the given collections iter times equal to the lowest length:
julia> length((3, 3)), length(tups)
(2, 3)
So it iterates two times, not three. To make that work, you can repeat the (3, 3), three times or even omit the (3, 3) argument:
julia> map((x, y) -> √(sum((x.-y).^2)), tups, ((3, 3), (3, 3), (3, 3)))
3-element Vector{Float64}:
2.0
8.06225774829855
3.605551275463989
# OR
julia> map((x, y) -> √(sum((x.-y).^2)), tups, ((3, 3) for _∈1:3))
3-element Vector{Float64}:
2.0
8.06225774829855
3.605551275463989
# Or omit the last argument
julia> map(arg -> √((3 - arg[1])^2 + (3 - arg[2])^2), tups)
3-element Vector{Float64}:
2.0
8.06225774829855
3.605551275463989

How to interate over two or more vectors or tuples in julia?

Can we iterate over two or more vectors or tuples in julia?
julia> c=Tuple(x for x in a, b)
The above code does not work but shows what i want to do. I need to iterate over both a and b one after other.
Suppose,
julia> a=(1,2)
julia> b=(3,4)
and I want c to be:
julia> c=(1,2,3,4)
Use:
julia> c = Tuple(Iterators.flatten((a, b)))
(1, 2, 3, 4)
to get a Tuple as you requested. But if you are OK with a lazy iterator then just Iterators.flatten((a, b)) is enough.
Very short version:
julia> a=(1,2)
julia> b=(3,4)
julia> c = (a..., b...)
(1, 2, 3, 4)

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)

Vector of matrices in 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}[ ]

Is there outer map function in Julia?

I am trying to construct all possible combinations of four vectors (parameters in a model) that would give me a big nx4 matrix and I could then run simulation on each set (row) of parameters. In R I would achieve this by using expand.grid in Mathematica style, I could use something like outer product with vcat and reduce the output using hcat.
Is there some function analog of expand.grid from R or outer map function?
Toy example:
A = [1 2]
B = [3 4]
some magic
output = [1 3, 1 4, 2 3, 2 4]
Using the Iterators package, it might look like this:
using Iterators
for p in product([1,2], [3,4])
println(p)
end
where you would replace println with your algorithm. You can also use collect if it's important to get the set of all combinations.
Not the exact notation you show, but a comprehension might be useful.
julia> a=[1, 2];
julia> b=[3, 4];
julia> [[i, j] for j in b, i in a]
2x2 Array{Any,2}:
[1,3] [2,3]
[1,4] [2,4]
julia> [[i, j] for j in b, i in a][:]
4-element Array{Any,1}:
[1,3]
[1,4]
[2,3]
[2,4]

Resources