How to split array in Julia like in Python? - arrays

I want to do this :
a = [1,2,3,4,5]
print(a[:2])
The output is
[1, 2]
How can I do the same things in Julia? But my a is of type : Array{Array{Float64,1},1}

Assume you have:
julia> x = [[i] for i in 1.0:5.0]
5-element Array{Array{Float64,1},1}:
[1.0]
[2.0]
[3.0]
[4.0]
[5.0]
(this is an equivalent of you have written above but with the types you request).
You can slice x by passing the first and the last index of the slice. Both lower and upper bound will be included (also note that Julia uses 1-based indexing):
julia> x[1:2]
2-element Array{Array{Float64,1},1}:
[1.0]
[2.0]
julia> x[2:4]
3-element Array{Array{Float64,1},1}:
[2.0]
[3.0]
[4.0]
You can use end to indicate end of your collection:
julia> x[3:end]
3-element Array{Array{Float64,1},1}:
[3.0]
[4.0]
[5.0]
The above operations created a new vector. If you prefer to have a view then write:
julia> #view x[2:4]
3-element view(::Array{Array{Float64,1},1}, 2:4) with eltype Array{Float64,1}:
[2.0]
[3.0]
[4.0]
or
julia> view(x, 2:4)
3-element view(::Array{Array{Float64,1},1}, 2:4) with eltype Array{Float64,1}:
[2.0]
[3.0]
[4.0]
The difference is that with #view macro you can still use end, e.g. #view x[2:end], but view function does not support it.

Related

Prevent type changes when constructing an Array{Any} in Julia

I want to make an Array{Any} like this:
julia> Array{Any}([false , 0.5, 5 ])
3-element Vector{Any}:
0.0
0.5
5.0
but it converts the Bool and the integer to floats. But when I have a string it does not do type conversions.
julia> Array{Any}([false,0.5,5,"test"])
4-element Vector{Any}:
false
0.5
5
"test"
The easy workaround is to make the array and then do a manual conversion of every entry to the type I originally wrote. Or do the second option and then delete the final entry. Is there a cleaner (ideally one line) way to make the array in exactly the types I originally wrote though?
Just do:
julia> Any[false, 0.5, 5]
3-element Vector{Any}:
false
0.5
5
Note that:
julia> [false, 0.5, 5]
3-element Vector{Float64}:
0.0
0.5
5.0
Hence it is creating a Vector of Float64 because this is a type that captures all value and wrapping that with Vector{Any}() was too late.
If you don't care about types and compilation acceleration you can just write:
julia> [false,0.5,5,"test"]
4-element Vector{Any}:
false
0.5
5
"test"
If you care a little more about types you could use this:
julia> a = Union{Bool, Float64, Int, String}[false, 0.5, 5, "test"]
4-element Vector{Union{Bool, Float64, Int64, String}}:
false
0.5
5
"test"
It's better but not great. Heterogenous arrays are not a good practice in Julia. Structuring your data by using composite types or tuples makes things more readable (and self-documented) and can potentially improve your performance.

Resize Vectors Julia

So I am trying to re-size vector of vectors in Julia like this:
A = [Vector{Any}() for i in 1:6]
a, b, c, d, e, f, g, h = 3, 4, 5, 6, 7, 8, 9, 10
for tt = 1:6
a+=1
resize!(A[tt], a)
for rr = 1:a
b+=1
resize!(A[tt][rr], b)
for tt2 = 1:b
resize!(A[tt][rr][tt2], b)
end
end
end
I am getting this error:
UndefRefError: access to undefined reference
Stacktrace: [1] getindex(::Array{Any,1}, ::Int64) at ./array.jl:549
[2] macro expansion at ./In[70]:7 [inlined] [3] anonymous at
./:?
Any help please?
There are two problems with your code.
Problem 1. resize! changes the size of the vector but does not initialize its elements. If vector has element type Any then the entries will be #undef which means uninitialized. You have to initialize them first before accessing.
Here is an example:
julia> A = Any[]
0-element Array{Any,1}
julia> resize!(A, 1)
1-element Array{Any,1}:
#undef
julia> resize!(A[1], 1) # you get an error
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getindex(::Array{Any,1}, ::Int64) at .\array.jl:549
julia> A[1] = Any[]
0-element Array{Any,1}
julia> A
1-element Array{Any,1}:
Any[]
julia> resize!(A[1], 1) # now it works
1-element Array{Any,1}:
#undef
julia> A
1-element Array{Any,1}:
Any[#undef]
Problem 2. Your code will not work under Julia 1.0, because you are trying to modify a global variable inside a loop (e.g. a in line a += 1). Wrap your code inside a function or let block to make it not throw an error.

How to fill an array with a given value (not object reference)?

As a followup to this question, how can you create an array filled with copies rather than references in Julia?
To use an example, how to create a function like fill that behaves like a when modifying elements of the array?
julia> a = [[],[]]
2-element Array{Array{Any,1},1}:
Any[]
Any[]
julia> push!(a[1],1.0)
1-element Array{Any,1}:
1.0
julia> a
2-element Array{Array{Any,1},1}:
Any[1.0]
Any[]
julia> b = fill([],2)
2-element Array{Array{Any,1},1}:
Any[]
Any[]
julia> push!(b[1],1.0)
1-element Array{Any,1}:
1.0
julia> b
2-element Array{Array{Any,1},1}:
Any[1.0]
Any[1.0]
Comprehension, could help:
julia> a=[[] for i=1:4]
4-element Array{Array{Any,1},1}:
Any[]
Any[]
Any[]
Any[]
julia> push!(a[1],1)
1-element Array{Any,1}:
1
julia> a
4-element Array{Array{Any,1},1}:
Any[1]
Any[]
Any[]
Any[]

Julia language: sub vs. slice function

Could someone explain in simple terms the difference between julia's v0.4 function:
sub and slice (and maybe slicedim)
Some simple example would be greatly appriciated.
Thanks a lot
The difference is that slice drops all dimensions "sliced" with a scalar (non-vector), while sub often retains them. For example:
julia> A = rand(3,3)
3x3 Array{Float64,2}:
0.403464 0.229403 0.924686
0.953741 0.175086 0.49139
0.0290678 0.705564 0.567355
julia> a = slice(A, 2, :) # this will be 1-dimensional
3-element SubArray{Float64,1,Array{Float64,2},(Int64,Colon),2}:
0.953741
0.175086
0.49139
julia> b = sub(A, 2, :) # this will be 2-dimensional
1x3 SubArray{Float64,2,Array{Float64,2},(UnitRange{Int64},Colon),2}:
0.953741 0.175086 0.49139
julia> size(a)
(3,)
julia> size(b)
(1,3)
There's one exception: sub drops dimensions indexed with a scalar if they are "trailing" dimensions, meaning there are no later dimensions indexed with a vector:
julia> a = slice(A, :, 2)
3-element SubArray{Float64,1,Array{Float64,2},(Colon,Int64),2}:
0.229403
0.175086
0.705564
julia> b = sub(A, :, 2)
3-element SubArray{Float64,1,Array{Float64,2},(Colon,Int64),2}:
0.229403
0.175086
0.705564
julia> size(a)
(3,)
julia> size(b)
(3,)
If you slice with a range, then you get behavior like sub:
julia> a = slice(A, 2:2, :)
1x3 SubArray{Float64,2,Array{Float64,2},(UnitRange{Int64},Colon),1}:
0.953741 0.175086 0.49139
julia> size(a)
(1,3)
It's not the length of the index that matters, it's the type: any dimension indexed with a non-scalar will be retained.

Getting 1D Subsets of Multi dimensional arrays in julia

I have a multi dimensional array in julia:
julia> ac.value
3x100x3 Array{Float64,3}:
[:, :, 1] =
0.29238 0.0751815 0.00843636 … -0.0143826 0.0403283 0.0225896
0.263146 0.080687 0.000462262 -0.00635778 0.0307563 0.0379104
0.992458 0.986423 0.980587 0.561173 0.55516 0.549105
[:, :, 2] =
0.362155 0.13406 0.0741124 … 0.0231614 0.0156455 0.0121797
0.325581 0.11181 0.0447847 0.0098042 0.0193873 0.0146943
0.914888 0.852297 0.796608 -0.0500265 -0.0551787 -0.0520171
[:, :, 3] =
0.269976 0.108082 0.0441809 … 0.0249861 0.0128778 0.0168318
0.218475 0.0997567 0.0532782 0.0243412 0.00742072 0.00978782
0.96878 0.947455 0.931407 0.0796884 0.0710757 0.0630705
When I look at
julia> ac.value[1,:,1]
1x100 Array{Float64,2}:
0.29238 0.0751815 0.00843636 … -0.0143826 0.0403283 0.0225896
I get a 2 dimensional array, but when I look at
julia> ac.value[:,1,1]
3-element Array{Float64,1}:
0.29238
0.263146
0.992458
I get a one dimensional array. Why is this so and what can I do so that in the former case I get a one-dimensional array?
A quick hack to get 1D arrays is to append [:] to your array references. E.g.,
julia> A = rand(Int,3,3,3)
3x3x3 Array{Int32,3}:
[:, :, 1] =
1059011904 -1092196516 -2083742447
-1232110963 46419394 599245389
747779547 1800837260 -460798437
[:, :, 2] =
-154984919 1641929284 1335793910
-1575337246 1100743707 333491108
231729201 1543773782 338937245
[:, :, 3] =
-1812252712 374672056 -156561770
317145782 -1941995702 747015018
127966143 -102265949 1068453724
julia> A[:,1,1]
3-element Array{Int32,1}:
1059011904
-1232110963
747779547
julia> A[:,1,1][:]
3-element Array{Int32,1}:
1059011904
-1232110963
747779547
julia> A[1,:,1]
1x3 Array{Int32,2}:
1059011904 -1092196516 -2083742447
julia> A[1,:,1][:]
3-element Array{Int32,1}:
1059011904
-1092196516
-2083742447
julia> A[1,1,:]
1x1x3 Array{Int32,3}:
[:, :, 1] =
1059011904
[:, :, 2] =
-154984919
[:, :, 3] =
-1812252712
julia> A[1,1,:][:]
3-element Array{Int32,1}:
1059011904
-154984919
-1812252712
You may also be interested in the ArrayViews package which may be more efficient depending on what you want to implement.

Resources