Working with Matrices


Subscripts

Subscripts are special postfix operators placed in square brackets ([ ]) after a matrix operand. Subscript operations have the general form operand[row,column] where

operand

is usually a matrix name, but it can also be an expression or literal.

row

refers to a scalar or vector expression that selects one or more rows from the operand.

column

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.

Selecting a Single Element

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;

Figure 5.18: Datum Extracted from a Matrix with Assigned Attributes

cSamMon
5



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;

Figure 5.19: Datum Extracted from a Matrix by Specifying the Element Number

c16
5



Selecting a Row or Column

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;

Figure 5.20: Row Extracted from a Matrix

jim
2 1 0 2 1

jim2
2 1 0 2 1



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;

Figure 5.21: Column Extracted from a Matrix

friday
2
1
1
4



Alternatively, you could also index by the column name as follows:

friday = coffee[,'FRI'];

Submatrices

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;

Figure 5.22: Submatrix Extracted from a Matrix

submat1
2 2 2
1 0 1



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;

Figure 5.23: Submatrix of Contiguous Rows and Columns

submat2
2 3 2
1 2 1
0 2 1



Selecting Multiple Elements

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 $n\times p$ matrix. The elements in the first row have positions 1 through p, the elements in the second row have positions $p+1$ through $2p$, and the elements in the last row have positions $(n-1)p+1$ through $np$.

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;

Figure 5.25: Values That Correspond to a Criterion

cups
4
3
3
3
5
4
4
3
4



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;

Figure 5.26: Column Vector of Extracted Values

v2
-1
5
7



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;

Figure 5.27: Row Vector of Extracted Values

v3
-1 5 7



Subscripted Assignment

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;

Figure 5.29: Results of Finding and Replacing Negative Values

i
3 5

t
3 2 0
6 0 3
2 2 2



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.