
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# [1], squares# [2], squares# [3], squares# [4] and squares# [5]. 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 precomputed 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.
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)
To create a vector containing the integer numbers 1 through 64, you use
to# (64)
To create a vector containing the integer numbers 10 through 20, you use
from_to# (10, 20)
To create a vector containing linearly increasing (not necessarily integer) numbers from 10 through 20 in steps of 2, you use
from_to_by# (10, 20, 2)
To create five linearly increasing numbers between 0 and 10 (i.e. { 0, 2.5, 5, 7.5, 10 }), you use
from_to_count# (0, 10, 5)
To divide the range between 0 and 12 symmetrically with step 5 (i.e. { 1, 6, 11 }), you use
between_by# (0, 12, 5)
To divide the range between 0 and 10 into five equal parts and list their centres (i.e. { 1, 3, 5, 7, 9 }), you use
between_count# (0, 10, 5)
To sort the numbers in a vector (e.g. { 7.4, 1.3, 3.6 }), you use
sort# ({ 7.4, 1.3, 3.6 })
which yields { 1.3, 3.6, 7.4 }.
To randomnly shuffle the numbers in a vector (e.g. { 7.4, 1.3, 3.6 }), you use
shuffle# ({ 7.4, 1.3, 3.6 })
which can yield { 1.3, 7.4, 3.6 } or any of the five other orders of the elements.
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"
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=1}^{5} squares[i] * other[i], so that an alternative piece of code could be
result = sumOver (i to 5, squares# [i] * other# [i])
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.01second 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"
A numeric matrix is a twoindexed 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.
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
m_{ij} = u_{i} v_{j} (i = 1..M, j = 1..N) 
where M is the number of rows and N is the number of columns.
You can add matrices:
c## = a## + b##
Elementwise multiplication:
c## = a## * b##
which does
c_{ij} = a_{ij} b_{ij} (i = 1..M, j = 1..N) 
Matrix multiplication:
c## = mul## (a##, b##)
which does
m_{ij} = ∑_{k=1}^{K} a_{ik} b_{kj} (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.
Matrixbyvector multiplication:
v# = mul# (m##, u#)
which does
v_{i} = ∑_{j=1}^{N} m_{ij} u_{j} (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
v_{j} = ∑_{i=1}^{M} u_{i} m_{ij} (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.
You can create string vactors in the following ways:
a$# = { "hello", "goodbye" }
creates a vector with two strings, which you can access as a$# [1]
, which is "hello", and a$# [2]
, which is "goodbye".
a$# = empty$# (10)
creates a vector with 10 empty strings, which you can access as a$# [1]
through a$# [10]
.
text$# = readLinesFromFile$# ("hello.txt")
creates a vector with 100 strings if the file hello.text
contains 100 lines of text.
fileNames$# = fileNames$# ("sound/*.wav")
creates a vector containing the names of all WAV files in the folder sound
.
folderNames$# = folderNames$# (".")
creates a vector containing the names of all folders in the folder where the script resides.
inks$# = splitByWhitespace$# ("Hello, how are you?")
creates a vector containing the strings "Hello,", "how", "are", and "you?".
© ppgb, December 29, 2020