Basic array creation

In [1]:
# Creating an empty array
my_array = []
Out[1]:
0-element Array{Any,1}
In [2]:
# Creating an empty array with an abstract type
my_array = (Integer)[]
Out[2]:
0-element Array{Integer,1}
In [3]:
# Creating an empty array with a concrete type (results in fastest operation)
my_array = (Float64)[]
Out[3]:
0-element Array{Float64,1}
In [4]:
# Array with three elements (here the type will be inferred automatically by Julia)
array1 = [1, 2, 3]
Out[4]:
3-element Array{Int64,1}:
 1
 2
 3

This would be akin to what we would consider a column vector in mathematics. We couls also create a row vector by omitting the commas.

In [5]:
array2 = [1 2 3]
Out[5]:
1×3 Array{Int64,2}:
 1  2  3

We could transpose array1, which would make it similar to array array2. Remember that a transpose action interchanges rows and columns.

In [6]:
# Syntax one
transpose(array1)
Out[6]:
1×3 LinearAlgebra.Transpose{Int64,Array{Int64,1}}:
 1  2  3
In [7]:
# Syntax 2
array1'
Out[7]:
1×3 LinearAlgebra.Adjoint{Int64,Array{Int64,1}}:
 1  2  3
In [8]:
# Is the transpose equal to the row array
array1' == array2
Out[8]:
true

But the type of the transposed array is not exactly same. Because the transpose comes from the LinearAlgebra module, the type of the array changes. We can use the === strict equality operator to test that

In [9]:
typeof(array1')
Out[9]:
LinearAlgebra.Adjoint{Int64,Array{Int64,1}}
In [10]:
array1'===array2
Out[10]:
false

If we mix various types of elements in an array, then arrays will take on the type of the element that is more encompassing. In the example below, two values will be of Int64 type, but the last is of Float64 type. The array will return the Float64 type.

In [11]:
array3 = [1, 2, 3.0]
Out[11]:
3-element Array{Float64,1}:
 1.0
 2.0
 3.0
In [12]:
array4 = ["one",pi,42]
Out[12]:
3-element Array{Any,1}:
   "one"
  π     
 42     
In [13]:
for i in array4
    println("Type of \'$i\' is $(typeof(i))")
end
Type of 'one' is String
Type of 'π' is Irrational{:π}
Type of '42' is Int64

We can create arrays with more than just a single row or column of elements. This would be akin to a mathematical matrix. We can even create multidimensional arrays. We achieve this by nesting our square brackets and playing with commas and semicolons.

In [14]:
# Note the omission of commas between the inner nested square brackets
array5 = [[1, 2, 3] [4, 5, 6] [7, 8, 9]]
Out[14]:
3×3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9
In [15]:
# If we want to populate the elements along row first, we use semicolons
array6 = [[1 2 3]; [4 5 6]; [7 8 9]]
Out[15]:
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

Size and dimension

  • length()
  • size()
  • ndims()
In [16]:
# Checking how many elements we have
length(array6)
Out[16]:
9
In [17]:
# Checking size or dimension
size(array6)
Out[17]:
(3, 3)
In [18]:
# The number of dimension
a = rand(3,2,2);
a
Out[18]:
3×2×2 Array{Float64,3}:
[:, :, 1] =
 0.764738   0.24668 
 0.0558193  0.607287
 0.284665   0.872515

[:, :, 2] =
 0.707157  0.403172
 0.48482   0.034637
 0.38063   0.403689
In [19]:
println(ndims(a))
3

Creating and reshaping

Repeating values is easily accomplished with the repeat([arrayvalues], number of repititions) function.

In [20]:
# Repeating the values 1 and 2 along a column
repeat([1, 2], 3)
Out[20]:
6-element Array{Int64,1}:
 1
 2
 1
 2
 1
 2
In [21]:
# ...or each value as a row (note no comma in the array definition)
repeat([1 2],3)
Out[21]:
3×2 Array{Int64,2}:
 1  2
 1  2
 1  2

We can use built-in functions to create arrays. These can be used in other ways as we will see later.

The range(start value, end value, number of steps) can be used as an array.

In [22]:
# The values 0 to 10
range(0, 10, length=11)
Out[22]:
0.0:1.0:10.0

To access the actuale values, we use the collect() function.

In [23]:
array7 = collect(range(0, 10, length=11))
Out[23]:
11-element Array{Float64,1}:
  0.0
  1.0
  2.0
  3.0
  4.0
  5.0
  6.0
  7.0
  8.0
  9.0
 10.0

To create a logarithmic range i.e. to create a $10^i$ to $10^𝑓$ collection of 20 values...

In [24]:
# i = 2 and f = 3, Note the space between 10 and .^
array8 = collect(10 .^(range(2, 3, length=20)))
Out[24]:
20-element Array{Float64,1}:
  100.0             
  112.88378916846895
  127.42749857031335
  143.8449888287663 
  162.37767391887226
  183.29807108324357
  206.913808111479  
  233.57214690901213
  263.6650898730358 
  297.63514416313194
  335.9818286283781 
  379.26901907322497
  428.13323987193957
  483.2930238571752 
  545.559478116852  
  615.8482110660261 
  695.1927961775605 
  784.7599703514614 
  885.8667904100823 
 1000.0             
In [25]:
array9 = collect(0:1:5)
Out[25]:
6-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5
In [26]:
array10 = collect(0:2:5)
Out[26]:
3-element Array{Int64,1}:
 0
 2
 4
In [27]:
# Creating an empty array of two rows and three columns
# Using an abstract type to leave the values empty
array11 = Array{Integer}(undef, 2,3)
Out[27]:
2×3 Array{Integer,2}:
 #undef  #undef  #undef
 #undef  #undef  #undef
In [28]:
# Specifying a concrete (numerical) type will add random value
array12 = Array{Int64}(undef,3, 3)
Out[28]:
3×3 Array{Int64,2}:
 0  0  0
 0  0  0
 0  0  0

Speical functions like ones() and zeros() can be used to create arrays with 1's and 0's respectively. Another function fill() can be used to fill an array with a pre-determined value.

In [29]:
ones(5)
Out[29]:
5-element Array{Float64,1}:
 1.0
 1.0
 1.0
 1.0
 1.0
In [30]:
zeros(4)
Out[30]:
4-element Array{Float64,1}:
 0.0
 0.0
 0.0
 0.0
In [31]:
ones((2,3))
Out[31]:
2×3 Array{Float64,2}:
 1.0  1.0  1.0
 1.0  1.0  1.0
In [32]:
fill(3.5,(3,2))
Out[32]:
3×2 Array{Float64,2}:
 3.5  3.5
 3.5  3.5
 3.5  3.5
In [33]:
fill("Julia",(2,3))
Out[33]:
2×3 Array{String,2}:
 "Julia"  "Julia"  "Julia"
 "Julia"  "Julia"  "Julia"

Lastly, in this section, we will take a look at reshaping an array. Given an array of elements, we can simply change its dimensions using the reshape() function.

In [34]:
# Remember array7
array9
Out[34]:
6-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5
In [35]:
# Reshaping it into an array with 2 rows and 3 columns
reshape(array9, 2, 3)
Out[35]:
2×3 Array{Int64,2}:
 0  2  4
 1  3  5
In [36]:
# Reshaping it into an array with 3 rows and 2 columns
reshape(array9, 3, 2)
Out[36]:
3×2 Array{Int64,2}:
 0  3
 1  4
 2  5

Slicing

When arrays get to larger and larger size, we may want to select only sections of it, based on some rule or rules. In this section we recap some of the ways in which this can be achieved and add some new ones.

The rand() function returns a random value between 0 and 1. We can also specify values to select from. In the example below we choose integers in the range [10, 20] and create an array with ten rows and five columns.

In [37]:
array13 = rand(10:20, 10, 5)
Out[37]:
10×5 Array{Int64,2}:
 12  20  18  10  12
 20  20  19  18  15
 16  11  11  12  18
 10  18  20  14  18
 18  20  16  11  20
 17  10  12  10  16
 18  11  10  14  13
 19  19  19  17  10
 16  16  15  20  16
 10  10  18  11  11
In [38]:
# Selecting all row values in column 2
array13[:, 2]
Out[38]:
10-element Array{Int64,1}:
 20
 20
 11
 18
 20
 10
 11
 19
 16
 10
In [39]:
# All row values in columns 2 and 5
array13[:, [2, 5]]
Out[39]:
10×2 Array{Int64,2}:
 20  12
 20  15
 11  18
 18  18
 20  20
 10  16
 11  13
 19  10
 16  16
 10  11
In [40]:
# All row values in columns 2, 3, and 4
array13[:, 2:4]
Out[40]:
10×3 Array{Int64,2}:
 20  18  10
 20  19  18
 11  11  12
 18  20  14
 20  16  11
 10  12  10
 11  10  14
 19  19  17
 16  15  20
 10  18  11
In [41]:
# Values in rows 2, 4, 6, and in columns 1 and 5
array13[[2, 4, 6], [1, 5]]
Out[41]:
3×2 Array{Int64,2}:
 20  15
 10  18
 17  16
In [42]:
# Values in row 1 from column 3 to the last column
array13[1, 3:end]
Out[42]:
3-element Array{Int64,1}:
 18
 10
 12

Logic on arrays

Now we take a look at applying some rules. Note how we use the element-wise logic operator in the form of the dot (note the .> operator in the code below).

Furthermore, by using the findall() function we can return the index values.

In [43]:
# Boolean logic (returning only true and false)
array13[:, 1] .> 14
Out[43]:
10-element BitArray{1}:
 0
 1
 1
 0
 1
 1
 1
 1
 1
 0
In [44]:
# Returning the index of true values using findall()
findall(array13[:, 1] .> 14)
Out[44]:
7-element Array{Int64,1}:
 2
 3
 5
 6
 7
 8
 9

Sorting and min/max

In [45]:
array13
Out[45]:
10×5 Array{Int64,2}:
 12  20  18  10  12
 20  20  19  18  15
 16  11  11  12  18
 10  18  20  14  18
 18  20  16  11  20
 17  10  12  10  16
 18  11  10  14  13
 19  19  19  17  10
 16  16  15  20  16
 10  10  18  11  11
In [46]:
# Sorting along rows
sort(array13,dims=1)
Out[46]:
10×5 Array{Int64,2}:
 10  10  10  10  10
 10  10  11  10  11
 12  11  12  11  12
 16  11  15  11  13
 16  16  16  12  15
 17  18  18  14  16
 18  19  18  14  16
 18  20  19  17  18
 19  20  19  18  18
 20  20  20  20  20
In [47]:
# Sorting along columns
sort(array13,dims=2)
Out[47]:
10×5 Array{Int64,2}:
 10  12  12  18  20
 15  18  19  20  20
 11  11  12  16  18
 10  14  18  18  20
 11  16  18  20  20
 10  10  12  16  17
 10  11  13  14  18
 10  17  19  19  19
 15  16  16  16  20
 10  10  11  11  18
In [48]:
# Returns the max (the first one in case of more than one) and its index in a tuple
findmax(array13)
Out[48]:
(20, CartesianIndex(2, 1))
In [49]:
findmin(array13)
Out[49]:
(10, CartesianIndex(4, 1))
In [50]:
argmax(array13)
Out[50]:
CartesianIndex(2, 1)
In [51]:
argmin(array13)
Out[51]:
CartesianIndex(4, 1)

Modification

Collections of elements in the form of arrays can be made much more useful if we could alter the actual values.

We'll start off by adding elemnts to the end of an existing array. This can be done with the push()! function. Later, we will add a value at the start of an array using the pushfirst!() function. We will also look at splice! and append functions.

In [52]:
array14 = [1, 2, 3, 4]
Out[52]:
4-element Array{Int64,1}:
 1
 2
 3
 4
In [53]:
# Adding the value 5 at the end of the array
push!(array14, 5)
Out[53]:
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

As usual, the exclamation mark reminds you that this function changes the array.

In [54]:
# Adding the value 0 at the start of the array
pushfirst!(array14, 0)
Out[54]:
6-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5

To insert an element into an array at a given index, use the splice!() function. For example, here's a list of numbers with an obvious omission:

In [55]:
array14 = [1, 2, 3, 5, 6, 7, 8, 9]
Out[55]:
8-element Array{Int64,1}:
 1
 2
 3
 5
 6
 7
 8
 9

Use splice!() to insert a sequence at a specific range of index values. Julia returns the values that were replaced. The array grows larger to accommodate the new elements, and elements after the inserted sequence are pushed down. Let's insert, at position 4:5, the range of numbers 4:6:

In [56]:
splice!(array14, 4:5, 4:6)
Out[56]:
2-element Array{Int64,1}:
 5
 6
In [57]:
array14
Out[57]:
9-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9

If you don't supply a replacement, you can also use splice!() to remove elements and move the rest of them along.

In [58]:
splice!(array14,6:8)
Out[58]:
3-element Array{Int64,1}:
 6
 7
 8
In [59]:
array14
Out[59]:
6-element Array{Int64,1}:
 1
 2
 3
 4
 5
 9

To remove the last element use pop!

In [60]:
pop!(array14)
Out[60]:
9
In [61]:
array14
Out[61]:
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

... and to remove the first, popfirst!

In [62]:
popfirst!(array14)
Out[62]:
1
In [63]:
array14
Out[63]:
4-element Array{Int64,1}:
 2
 3
 4
 5

The function append! can be used to push a second collection at the back of the first one

In [64]:
a1 = collect(1:5);
a2 = collect(101:105);
append!(a1,a2)
Out[64]:
10-element Array{Int64,1}:
   1
   2
   3
   4
   5
 101
 102
 103
 104
 105

Array comprehension

In [65]:
# Create an array with elements 3.x^2 where x is an odd number between 1 and 9 (inclusive)
array15 = [3*i^2 for i in 1:2:9]
Out[65]:
5-element Array{Int64,1}:
   3
  27
  75
 147
 243
In [66]:
# Can use multiple variables for the initialization of 2D array
array16 = [a+2b for a in -1:1, b in -2:2]
Out[66]:
3×5 Array{Int64,2}:
 -5  -3  -1  1  3
 -4  -2   0  2  4
 -3  -1   1  3  5
In [67]:
# Array of squared elements if the square is not divisible by 5 or 4 (note that we need to use &&)
array17=[i^2 for i=1:10  if (i^2%5!=0 && i^2%4!=0)]
Out[67]:
4-element Array{Int64,1}:
  1
  9
 49
 81

Simple summary operations

  • sum
  • prod
  • mean
  • std
  • middle
  • median
In [68]:
array17
Out[68]:
4-element Array{Int64,1}:
  1
  9
 49
 81
In [69]:
sum(array17)
Out[69]:
140
In [70]:
prod(array17)
Out[70]:
35721

Functions like mean(), std() and middle() have been moved into the Statistics module in the standard library; you may need to first enter "using Statistics" to use them

In [71]:
using Statistics
In [72]:
mean(array17)
Out[72]:
35.0
In [73]:
std(array17)
Out[73]:
37.16629297271027
In [74]:
middle(array17)
Out[74]:
41.0
In [75]:
median(array17)
Out[75]:
29.0

For 2D arrays, we can specify dimensions (axis) along which the summary operation is to be performed

In [76]:
array16
Out[76]:
3×5 Array{Int64,2}:
 -5  -3  -1  1  3
 -4  -2   0  2  4
 -3  -1   1  3  5
In [77]:
std(array16)
Out[77]:
3.0472470011002204
In [78]:
mean(array16,dims=1)
Out[78]:
1×5 Array{Float64,2}:
 -4.0  -2.0  0.0  2.0  4.0
In [79]:
mean(array16,dims=2)
Out[79]:
3×1 Array{Float64,2}:
 -1.0
  0.0
  1.0

Element-wise operations

In [80]:
array18 = [2*a+b for a in 1:3, b in -2:2]
Out[80]:
3×5 Array{Int64,2}:
 0  1  2  3  4
 2  3  4  5  6
 4  5  6  7  8
In [81]:
array16
Out[81]:
3×5 Array{Int64,2}:
 -5  -3  -1  1  3
 -4  -2   0  2  4
 -3  -1   1  3  5
In [82]:
array16+array18
Out[82]:
3×5 Array{Int64,2}:
 -5  -2  1   4   7
 -2   1  4   7  10
  1   4  7  10  13
In [83]:
# Note the DOT in fron of the * to denote element-wise operation
array16.*array18
Out[83]:
3×5 Array{Int64,2}:
   0  -3  -2   3  12
  -8  -6   0  10  24
 -12  -5   6  21  40
In [84]:
# Division can produce `Inf` values if divided by zero
array18./array16
Out[84]:
3×5 Array{Float64,2}:
 -0.0      -0.333333   -2.0  3.0      1.33333
 -0.5      -1.5       Inf    2.5      1.5    
 -1.33333  -5.0         6.0  2.33333  1.6    

We can even raise one array to the power of another array element-wise. But for this to work, at least one of them has to be a Float type, not Integer. So, we create a Float64 array and demonstrate this.

In [85]:
array19 = (Float64)[a+b for a in 1:3, b in -1:3]
Out[85]:
3×5 Array{Float64,2}:
 0.0  1.0  2.0  3.0  4.0
 1.0  2.0  3.0  4.0  5.0
 2.0  3.0  4.0  5.0  6.0
In [86]:
array18.^array19
Out[86]:
3×5 Array{Float64,2}:
  1.0    1.0     4.0     27.0     256.0
  2.0    9.0    64.0    625.0    7776.0
 16.0  125.0  1296.0  16807.0  262144.0