Subscripts are special postfix operators placed in square brackets ([ ]) after a matrix operand. Subscript operations have the general form operand[row,column] where
is usually a matrix name, but it can also be an expression or literal.
refers to a scalar or vector expression that selects one or more rows from the operand.
refers to a scalar or vector expression that selects one or more columns from the operand.
You can use subscripts to do any of the following:
refer to a single element of a matrix
refer to an entire row or column of a matrix
refer to any submatrix contained within a matrix
perform a reduction across rows or columns of a matrix. A reduction is a statistical operation (often a sum or mean) applied to the rows or to the columns of a matrix.
In expressions, subscripts have the same (high) precedence as the transpose postfix operator (`). When both row and column subscripts are used, they are separated by a comma. If a matrix has row or column names associated with it from a MATTRIB or READ statement, then the corresponding row or column subscript can also be a character matrix whose elements match the names of the rows or columns to be selected.
You can select a single element of a matrix in several ways. You can use two subscripts (row, column) to refer to its location, or you can use one subscript to index the elements in row-major order.
For example, for the coffee example used previously in this chapter, there are several ways to find the element that corresponds to the number of cups that Samuel drank on Monday.
First, you can refer to the element by row and column location. In this case, you want the fourth row and first column. The
following statements extract the datum and place it in the matrix c41
:
coffee={4 2 2 3 2, 3 3 1 2 1, 2 1 0 2 1, 5 4 4 3 4}; names={Jenny, Linda, Jim, Samuel}; print coffee[rowname=names]; c41 = coffee[4,1]; print c41;
Figure 5.17: Datum Extracted from a Matrix
coffee | |||||
---|---|---|---|---|---|
JENNY | 4 | 2 | 2 | 3 | 2 |
LINDA | 3 | 3 | 1 | 2 | 1 |
JIM | 2 | 1 | 0 | 2 | 1 |
SAMUEL | 5 | 4 | 4 | 3 | 4 |
c41 |
---|
5 |
You can also use row and column names, which can be assigned with an MATTRIB statement as follows:
mattrib coffee rowname=names colname={'MON' 'TUE' 'WED' 'THU' 'FRI'}; cSamMon = coffee['SAMUEL','MON']; print cSamMon;
You can also look for the element by enumerating the elements of the matrix in row-major order. In this case, you refer to
this element as the sixteenth element of coffee
:
c16 = coffee[16]; print c16;
To refer to an entire row of a matrix, specify the subscript for the row but omit the subscript for the column. For example,
to refer to the row of the coffee
matrix that corresponds to Jim, you can specify the submatrix that consists of the third row and all columns. The following
statements extract and print this submatrix:
jim = coffee[3,]; print jim;
Alternately, you can use the row names assigned by the MATTRIB statement. Both results are shown in Figure 5.20.
jim2 = coffee['JIM',]; print jim2;
If you want to extract the data for Friday, you can specify the subscript for the fifth column. You omit the row subscript to indicate that the operation applies to all rows. The following statements extract and print this submatrix:
friday = coffee[,5]; print friday;
Alternatively, you could also index by the column name as follows:
friday = coffee[,'FRI'];
You refer to a submatrix by specifying the rows and columns that determine the submatrix. For example, to create the submatrix
of coffee
that consists of the first and third rows and the second, third, and fifth columns, use the following statements:
submat1 = coffee[{1 3}, {2 3 5}]; print submat1;
The first vector, {1 3}
, selects the rows and the second vector, {2 3 5}
, selects the columns. Alternately, you can create the vectors of indices and use them to extract the submatrix, as shown
in following statements:
rows = {1 3}; cols = {2 3 5}; submat1 = coffee[rows,cols];
You can also use the row and column names:
rows = {'JENNY' 'JIM'}; cols = {'TUE' 'WED' 'FRI'}; submat1 = coffee[rows, cols];
You can use index vectors generated by the index creation operator (:) in subscripts to refer to successive rows or columns.
For example, the following statements extract the first three rows and last three columns of coffee
:
submat2 = coffee[1:3, 3:5]; print submat2;
All SAS/IML matrices are stored in row-major order. This means that you can index multiple elements of a matrix by listing the position of the elements in an matrix. The elements in the first row have positions 1 through , the elements in the second row have positions through , and the elements in the last row have positions through .
For example, in the coffee data discussed previously, you might be interested in finding occurrences for which some person (on some day) drank more than two cups of coffee. The LOC function is useful for creating an index vector for a matrix that satisfies some condition. The following statement uses the LOC function to find the data that satisfy the desired criterion:
h = loc(coffee > 2); print h;
Figure 5.24: Indices That Correspond to a Criterion
h | |||||||||
---|---|---|---|---|---|---|---|---|---|
COL1 | COL2 | COL3 | COL4 | COL5 | COL6 | COL7 | COL8 | COL9 | |
ROW1 | 1 | 4 | 6 | 7 | 16 | 17 | 18 | 19 | 20 |
The row vector h
contains indices of the coffee
matrix that satisfy the criterion. If you want to find the number of cups of coffee consumed on these occasions, you need
to subscript the coffee
matrix with the indices, as shown in the following statements:
cups = coffee[h]; print cups;
Notice that SAS/IML software returns a column vector when a matrix is subscripted by a single array of indices. This might
surprise you, but clearly the cups
matrix cannot be the same shape as the coffee
matrix since it contains a different number of elements. Therefore, the only reasonable alternative is to return either a
row vector or a column vector. Either would be a valid choice; SAS/IML software returns a column vector.
Even if the original matrix is a row vector, the subscripted matrix will be a column vector, as the following example shows:
v = {-1 2 5 -2 7}; /* v is a row vector */ v2 = v[{1 3 5}]; /* v2 is a column vector */ print v2;
If you want to index into a row vector and you want the resulting variable also to be a row vector, then use the following technique:
v3 = v[ ,{1 3 5}]; /* Select columns. Note the comma. */ print v3;
You can assign values into a matrix by using subscripts to refer to the element or submatrix. In this type of assignment,
the subscripts appear on the left side of the equal sign. For example, to assign the value 4 in the first row, second column
of coffee
, use subscripts to refer to the appropriate element in an assignment statement, as shown in the following statements and
in Figure 5.27:
coffee[1,2] = 4; print coffee;
To change the values in the last column of coffee
to zeros, use the following statements:
coffee[,5] = {0,0,0,0}; /* alternatively: coffee[,5] = 0; */ print coffee;
Figure 5.28: Matrices after Assigning Values to Elements
coffee | ||||
---|---|---|---|---|
4 | 4 | 2 | 3 | 2 |
3 | 3 | 1 | 2 | 1 |
2 | 1 | 0 | 2 | 1 |
5 | 4 | 4 | 3 | 4 |
coffee | ||||
---|---|---|---|---|
4 | 4 | 2 | 3 | 0 |
3 | 3 | 1 | 2 | 0 |
2 | 1 | 0 | 2 | 0 |
5 | 4 | 4 | 3 | 0 |
In the next example, you locate the negative elements of a matrix and set these elements to zero. (This can be useful in situations
where negative elements might indicate errors.) The LOC function is useful for creating an index vector for a matrix that
satisfies some criterion. The following statements use the LOC function to find and replace the negative elements of the matrix
T
:
t = {3 2 -1, 6 -4 3, 2 2 2 }; i = loc(t<0); print i; t[i] = 0; print t;
Subscripts can also contain expressions. For example, the previous example could have been written as follows:
t[loc(t<0)] = 0;
If you use a noninteger value as a subscript, only the integer portion is used. Using a subscript value less than one or greater than the dimension of the matrix results in an error.