5.5 Array data types
Stan supports arrays of arbitrary dimension. The values in an array can be any type, so that arrays may contain values that are simple reals or integers, vectors, matrices, or other arrays. Arrays are the only way to store sequences of integers, and some functions in Stan, such as discrete distributions, require integer arguments.
A two-dimensional array is just an array of arrays, both conceptually
and in terms of current implementation. When an index is supplied to
an array, it returns the value at that index. When more than one
index is supplied, this indexing operation is chained. For example, if
a
is a two-dimensional array, then a[m, n]
is just
a convenient shorthand for a[m][n]
.
Vectors, matrices, and arrays are not assignable to one another, even if their dimensions are identical.
For constructing arrays in Stan, see Vector, Matrix, and Array Expressions.
Declaring array variables
Arrays are declared with the keyword array
followed by the dimensions
enclosed in square brackets, the element type, and the name of the variable.
The variable n
is declared as an array of five integers as follows.
array[5] int n;
A two-dimensional array of real values with three rows and four columns is declared with the following.
array[3, 4] real a;
A three-dimensional array z
of positive reals with five rows, four
columns, and two shelves can be declared as follows.
array[5, 4, 2] real<lower=0> z;
Arrays may also be declared to contain vectors. For example,
array[3] vector[7] mu;
declares mu
to be an array of size 3 containing vectors with 7
elements. Arrays may also contain matrices. The example
array[15, 12] matrix[7, 2] mu;
declares a 15 by 12 array of \(7 \times 2\) matrices. Any of the constrained types may also be used in arrays, as in the declaration
array[2, 3, 4] cholesky_factor_cov[5, 6] mu;
of a \(2 \times 3 \times 4\) array of \(5 \times 6\) Cholesky factors of covariance matrices.
5.5.0.1 Array syntax before Stan 2.26
Before Stan 2.26, arrays were declared by enclosing the dimensions in square brackets following the name of the variable.
The pre-Stan 2.26 array syntax for the above examples is as follows.
int n[5];
real a[3, 4];
real<lower=0> z[5, 4, 2];
vector[7] mu[3];
matrix[7, 2] mu[15, 12];
cholesky_factor_cov[5, 6] mu[2, 3, 4];
Both syntaxes can be used, though the array
keyword syntax is recommended.
Accessing array elements and subarrays
If x
is a 1-dimensional array of length 5, then x[1]
is
the first element in the array and x[5]
is the last. For a \(3 \times 4\) array y
of two dimensions, y[1, 1]
is the first
element and y[3, 4]
the last element. For a three-dimensional
array z
, the first element is z[1, 1, 1]
, and so on.
Subarrays of arrays may be accessed by providing fewer than the full
number of indexes. For example, suppose y
is a two-dimensional
array with three rows and four columns. Then y[3]
is
one-dimensional array of length four. This means that y[3][1]
may be used instead of y[3, 1]
to access the value of the first
column of the third row of y
. The form y[3, 1]
is the
preferred form (see note in this chapter).
Assigning
Subarrays may be manipulated and assigned just like any other variables. Similar to the behavior of matrices, Stan allows blocks such as
array[9, 10, 11] real w;
array[10, 11] real x;
array[11] real y;
real z;
// ...
x = w[5];
y = x[4]; // y == w[5][4] == w[5, 4]
z = y[3]; // z == w[5][4][3] == w[5, 4, 3]
Arrays of matrices and vectors
Arrays of vectors and matrices are accessed in the same way as arrays of doubles. Consider the following vector and scalar declarations.
array[3, 4] vector[5] a;
array[4] vector[5] b;
vector[5] c;
real x;
With these declarations, the following assignments are legal.
b = a[1]; // result is array of vectors
c = a[1, 3]; // result is vector
c = b[3]; // same result as above
x = a[1, 3, 5]; // result is scalar
x = b[3, 5]; // same result as above
x = c[5]; // same result as above
Row vectors and other derived vector types (simplex and ordered) behave the same way in terms of indexing.
Consider the following matrix, vector and scalar declarations.
array[3,4] matrix[6, 5] d;
array[4] matrix[6, 5] e;
matrix[6, 5] f;
row_vector[5] g;
real x;
With these declarations, the following definitions are legal.
e = d[1]; // result is array of matrices
f = d[1,3]; // result is matrix
f = e[3]; // same result as above
g = d[1,3,2]; // result is row vector
g = e[3,2]; // same result as above
g = f[2]; // same result as above
x = d[1,3,5,2]; // result is scalar
x = e[3,5,2]; // same result as above
x = f[5,2]; // same result as above
x = g[2]; // same result as above
As shown, the result f[2]
of supplying a single index to a
matrix is the indexed row, here row 2 of matrix f
.
Partial array assignment
Subarrays of arrays may be assigned by indexing on the left-hand side of an assignment statement. For example, the following is legal.
array[I,J,K] real x;
array[J,K] real y;
array[K] real z;
// ...
x[1] = y;
x[1,1] = z;
The sizes must match. Here, x[1]
is a J
by K
array, as is y
.
Partial array assignment also works for arrays of matrices, vectors, and row vectors.
Mixing array, vector, and matrix types
Arrays, row vectors, column vectors and matrices are not interchangeable in Stan. Thus a variable of any one of these fundamental types is not assignable to any of the others, nor may it be used as an argument where the other is required (use as arguments follows the assignment rules).
Mixing vectors and arrays
For example, vectors cannot be assigned to arrays or vice-versa.
array[4] real a;
vector[4] b;
row_vector[4] c;
// ...
a = b; // illegal assignment of vector to array
b = a; // illegal assignment of array to vector
a = c; // illegal assignment of row vector to array
c = a; // illegal assignment of array to row vector
Mixing row and column vectors
It is not even legal to assign row vectors to column vectors or vice versa.
vector[4] b;
row_vector[4] c;
// ...
b = c; // illegal assignment of row vector to column vector
c = b; // illegal assignment of column vector to row vector
Mixing matrices and arrays
The same holds for matrices, where 2-dimensional arrays may not be assigned to matrices or vice-versa.
array[3,4] real a;
matrix[3,4] b;
// ...
a = b; // illegal assignment of matrix to array
b = a; // illegal assignment of array to matrix
Mixing matrices and vectors
A \(1 \times N\) matrix cannot be assigned a row vector or vice versa.
matrix[1,4] a;
row_vector[4] b;
// ...
a = b; // illegal assignment of row vector to matrix
b = a; // illegal assignment of matrix to row vector
Similarly, an \(M \times 1\) matrix may not be assigned to a column vector.
matrix[4,1] a;
vector[4] b;
// ...
a = b; // illegal assignment of column vector to matrix
b = a; // illegal assignment of matrix to column vector
Size declaration restrictions
An integer expression is used to pick out the sizes of arrays. The same restrictions as for vector and matrix sizes apply, namely that the size is declared with an integer-denoting expression that does not contain any parameters, transformed parameters, or generated quantities.
Size zero arrays
If any of an array’s dimensions is size zero, the entire array will be of size zero. That is, if we declare
array[3, 0] real a;
then the resulting size of a
is zero and querying any of its
dimensions at run time will result in the value zero. Declared as
above, a[1]
will be a size-zero one-dimensional array. For
comparison, declaring
array[0, 3] real b;
also produces an array with an overall size of zero, but in this case,
there is no way to index legally into b
, because b[0]
is
undefined. The array will behave at run time as if it’s a \(0 \times 0\) array. For example, the result of to_matrix(b)
will be a
\(0 \times 0\) matrix, not a \(0 \times 3\) matrix.