In R, we could give names to each items in a vector:
> x = c( 2.718 , 3.14 , 1.414 , 47405 ) # define the vector
> names(x) = c( "e" , "pi" , "sqrt2" , "zipcode" ) # name the components
> x[c(2,4)] # which indices to include
pi zipcode
3.14 47405.00
> x[c(-1,-3)] # which indices to exclude
pi zipcode
3.14 47405.00
> x[c(FALSE,TRUE,FALSE,TRUE)] # for each position, include it?
pi zipcode
3.14 47405.00
In Julia, my first thought is using a Dict:
julia> x = [2.718, 3.14, 1.414, 47405]
4-element Array{Float64,1}:
2.718
3.14
1.414
47405.0
julia> namelist = ["e", "pi", "sqrt2", "zipcode"]
4-element Array{ASCIIString,1}:
"e"
"pi"
"sqrt2"
"zipcode"
julia> xdict=Dict(zip(namelist, x))
Dict{ASCIIString,Float64} with 4 entries:
"e" => 2.718
"zipcode" => 47405.0
"pi" => 3.14
"sqrt2" => 1.414
julia> xdict["pi"]
3.14
However, Dict lost the order of the original array, meaning I cannot access items like in R:
julia> xdict[[2,4]]
ERROR: KeyError: [2,4] not found in getindex at dict.jl:718
Is there something like named array in Julia? If not, what's the Julia-way to handle this kind of problem?
Trying to replicate the R code using NamedArrays:
julia> using NamedArrays
julia> xx = NamedArray([2.718, 3.14, 1.414, 47405],
(["e", "pi", "sqrt2", "zipcode"],))
4-element NamedArrays.NamedArray...
e 2.718
pi 3.14
sqrt2 1.414
zipcode 47405.0
julia> xx[[2,4]]
2-element NamedArrays.NamedArray...
pi 3.14
zipcode 47405.0
julia> xx[setdiff(1:end,[1,3])]
2-element NamedArrays.NamedArray...
pi 3.14
zipcode 47405.0
julia> xx[[1:end...][[false,true,false,true]]]
2-element NamedArrays.NamedArray...
pi 3.14
zipcode 47405.0
The indexing techniques are less than optimal. Improvements are welcome in the comments. It is also possible to enhance NamedArrays easily for better indexing (which would be harder in R).
Julia has the named tuple, which is the equivalent data structure and can be created like this:
(e=2.718, pi=3.14159, sqrt2 = 1.44, zipcode=47405)
Related
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)
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).
Does a cell array exist in Julia? I want an array which its elements are vector or matrix.
for example A={1,[2 3],[5 6;7 8];"salam", [1 2 3 4],magic(5)}.
if you don't mind please help me.
An Array{Any} is equivalent to a MATLAB cell array. You can put anything in there. ["hi",:bye,10]. a = Array{Any}(undef,5) builds an uninitialized one, you can a[1] = ... to modify values, push!(a,...) to increase its length, etc.
A cell array is a data type with indexed data containers called cells, where each cell can contain any type of data
In Julia, arrays can contain values of homogeneous ([1, 2, 3]) or heterogeneous types ([1, 2.5, "3"]). Julia will try to promote the values to a common concrete type by default. If Julia can not promote the types contained, the resulting array would be of the abstract type Any.
Example ported from Access Data in Cell Array, using Julia 1.0.3:
julia> C = ["one" "two" "three"; # Matrix literal
1 2 3 ]
2×3 Array{Any,2}:
"one" "two" "three"
1 2 3
julia> upperLeft = C[1:2,1:2] # slicing
2×2 Array{Any,2}:
"one" "two"
1 2
julia> C[1,1:3] = ["first","second","third"] # slice assignment
3-element Array{String,1}:
"first"
"second"
"third"
julia> C
2×3 Array{Any,2}:
"first" "second" "third"
1 2 3
julia> numericCells = C[2,1:3]
3-element Array{Any,1}:
1
2
3
julia> last = C[2,3] # indexing
3
julia> C[2,3] = 300 # indexing assignment
300
julia> C
2×3 Array{Any,2}:
"first" "second" "third"
1 2 300
julia> r1c1, r2c1, r1c2, r2c2 = C[1:2,1:2] # destructuring
2×2 Array{Any,2}:
"first" "second"
1 2
julia> r1c1
"first"
julia> r2c1
1
julia> r1c2
"second"
julia> r2c2
2
julia> nums = C[2,:]
3-element Array{Any,1}:
1
2
300
Example ported from Combining Cell Arrays with Non-Cell Arrays:
Notice the use of the splice operator (...) to incorporate the values of the inner array into the outer one, and the usage of the Any[] syntax to prevent Julia from promoting the UInt8 to an Int.
julia> A = [100, Any[UInt8(200), 300]..., "Julia"]
4-element Array{Any,1}:
100
0xc8
300
"Julia"
The .( broadcast syntax, applies the function typeof element wise.
julia> typeof.(A)
4-element Array{DataType,1}:
Int64
UInt8
Int64
String
So in summary Julia doesn't need cell arrays, it uses parametric n-dimensional arrays instead. Also Julia only uses brackets for both slicing and indexing (A[n], A[i, j], A[a:b, x:y]), parenthesis after a variable symbol is reserved for function calls (foo(), foo(args...), foo(bar = "baz")).
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)
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}[ ]