Scripting 5.7. Vectors and matrices

### 1. What is a vector?

A numeric vector is an array of numbers, regarded as a single object. For instance, the squares of the first five integers can be collected in the vector { 1, 4, 9, 16, 25 }. In a Praat script, you can put a vector into a variable whose name ends in a number sign ("#"):

``` squares# = { 1, 4, 9, 16, 25 }```

After this, the variable squares# contains the value { 1, 4, 9, 16, 25 }. We say that the vector squares# has five dimensions, i.e. it contains five numbers.

Whereas in Scripting 3.2. Numeric variables we talked about a numeric variable as being analogous to a house where somebody (the numeric value) could live, a numeric vector with five dimensions can be seen as a street that contains five houses, which are numbered with the indexes 1, 2, 3, 4 and 5, each house containing a numeric value. Thus, the street squares# contains the following five houses: squares# , squares# , squares# , squares#  and squares# . Their values (the numbers that currently live in these houses) are 1, 4, 9, 16 and 25, respectively.

To list the five values with a loop, you could do:

``` writeInfoLine: "Some squares:"``` ``` for i from 1 to size (squares#)``` ```    appendInfoLine: "The square of ", i, " is ", squares# [i]``` ``` endfor```

Instead of the above procedure to get the vector squares#, with a pre-computed list of five squares, you could compute the five values with a formula, as in the example of Scripting 5.6. Arrays and dictionaries. However, in order to put a value into an element of the vector, you have to create the vector first (i.e., you have to build the whole street before you can put something in a house), so we start by creating a vector with five zeroes in it:

``` squares# = zero# (5)```

After this, squares# is the vector { 0, 0, 0, 0, 0 }, i.e., the value of each element is zero. Now that the vector (street) exists, we can put values into (populate) the five elements (houses):

``` for i from 1 to size (squares#)``` ```    squares# [i] = i * i``` ``` endfor```

After this, the variable `squares#` has the value { 1, 4, 9, 16, 25 }, as before, but now we had the computer compute the squares.

### 2. Creating a vector

You can create a vector in many ways. The first way we saw was with a vector literal, i.e. a series of numbers (or numeric formulas) between braces:

``` lengths# = { 1.83, 1.795, 1.76 }```

The second way we saw was to create a series of zeroes. To create a vector consisting of 10,000 zeroes, you do

``` zero# (10000)```

Another important type of vector is a series of random numbers. To create a vector consisting of 10,000 values drawn from a Gaussian distribution with true mean 0.0 and true standard deviation 1.0, you could do

``` noise# = randomGauss# (10000, 0.0, 1.0)```

To create a vector consisting of 10,000 values drawn from a uniform distribution of real numbers with true minimum 0.0 and true maximum 1.0, you use

``` randomUniform# (10000, 0.0, 1.0)```

To create a vector consisting of 10,000 values drawn from a uniform distribution of integer numbers with true minimum 1 and true maximum 10, you use

``` randomInteger# (10000, 1, 10)```

Vectors can also be created by some menu commands. For instance, to get vectors representing the times and pitch frequencies of the frames in a Pitch object, you can do

``` selectObject: myPitch``` ``` times# = List all frame times``` ``` pitches# = List values in all frames: "Hertz"```

### 3. Turning a vector into a number

For the vector defined above, you can compute the sum of the five values as

``` sum (squares#)```

which gives 55. You compute the average of the five values as

``` mean (squares#)```

which gives 11. You compute the standard deviation of the values as

``` stdev (squares#)```

which gives 9.669539802906858 (the standard deviation is undefined for vectors with fewer than 2 elements). The center of gravity of the distribution defined by regarding the five values as relative frequencies as a function of the index from 1 to 5 is computed by

``` center (squares#)```

which gives 4.090909090909091 (for a vector with five elements, the result will always be a number between 1.0 and 5.0). You compute the inner product of two equally long vectors as follows:

``` other# = { 2, 1.5, 1, 0.5, 0 }``` ``` result = inner (squares#, other#)```

which gives 1*2 + 4*1.5 + 9*1 + 16*0.5 + 25*0 = 25. The formula for this is ∑i=15 squares[i] * other[i], so that an alternative piece of code could be

``` result = sumOver (i to 5, squares# [i] * other# [i])```

### 4. Converting vectors to vectors

``` a# = squares# + 5 ; adding a number to each element of a vector```

causes a# to become the vector { 6, 9, 14, 21, 30 }.

``` b# = a# + { 3.14, 2.72, 3.16, -1, 7.5 } ; adding two vectors of the same length```

causes b# to become the vector { 9.14, 11.72, 17.16, 20, 37.5 }.

``` c# = b# / 2 ; dividing each element of a vector```

causes c# to become the vector { 4.57, 5.86, 8.58, 10, 18.75 }.

``` d# = b# * c# ; elementwise multiplication```

causes d# to become the vector { 41.7698, 68.6792, 147.2328, 200, 703.125 }.

A vector can also be given to a menu command that returns another vector. For instance, to get a vector representing the pitch frequencies at 0.01-second intervals in a Pitch object, you can do

``` selectObject: myPitch``` ``` tmin = Get start time``` ``` tmax = Get end time``` ``` times# = between_by# (tmin, tmax, 0.01)``` ``` pitches# = List values at times: times#, "hertz", "linear"```

### 5. What is a matrix?

A numeric matrix is a two-indexed array of numbers, regarded as a single object. In a Praat script, you can put a matrix into a variable whose name ends in two number signs ("##"):

``` confusion## = {{ 3, 6, 2 }, { 8, 2, 1 }}```

After this, the variable confusion## contains the value {{ 3, 6, 2 }, { 8, 2, 1 }}. We say that the matrix confusion# has two rows and three columns, i.e. it contains six numbers.

Whereas a numeric vector with five dimensions could be seen (see above) as a street that contains five houses, the matrix confusion## can be seen as a city district with two avenues crossed by three streets.

### 6. Creating a matrix

You can create a matrix in many ways. The first way we saw was with a matrix literal, i.e. a series of series of numbers (or numeric formulas) between nested braces.

The second way is as a matrix of zeroes. To create a matrix consisting of 100 rows of 10,000 zeroes, you do

``` a## = zero## (100, 10000)```

After this,

``` numberOfRows (a##)```

is 100, and

``` numberOfColumns (a##)```

is 10000.

Another important type of matrix is one filled with random numbers. To create a matrix consisting of 100 rows of 10,000 values drawn from a Gaussian distribution with true mean 0.0 and true standard deviation 1.0, you can do

``` noise## = randomGauss## (100, 10000, 0.0, 1.0)```

You can create a matrix as the outer product of two vectors:

``` m## = outer## (u#, v#)```

which is the same as

``` m## = zeros## (size (u#), size (v#))``` ``` for irow to size (u#)``` ```    for icol to size (v#)``` ```       m## [irow, icol] = u# [irow] * v# [icol]``` ```    endfor``` ``` endfor```

or in mathematical notation

 mij = ui vj (i = 1..M, j = 1..N)

where M is the number of rows and N is the number of columns.

### 7. Computations with matrices

``` c## = a## + b##```

Elementwise multiplication:

``` c## = a## * b##```

which does

 cij = aij bij (i = 1..M, j = 1..N)

Matrix multiplication:

``` c## = mul## (a##, b##)```

which does

 mij = ∑k=1K aik bkj (i = 1..M, j = 1..N)

where M is the number of rows of a, N is the number of columns of b, and K is the number of columns of a, which has to be equal to the number if rows of b.

Matrix-by-vector multiplication:

``` v# = mul# (m##, u#)```

which does

 vi = ∑j=1N mij uj (i = 1..M)

where M is the number of rows of m, and N is the number of columns of m, which has to be equal to the dimension of u. Also

``` v# = mul# (u#, m##)```

which does

 vj = ∑i=1M ui mij (j = 1..N)

where M is the number of rows of m, which has to be equal to the dimension of u, and N is the number of columns of m.