MATRIX

<< Click to Display Table of Contents >>

Navigation:  Gekko User Manual > Gekko statements >

MATRIX

Previous pageReturn to chapter overviewNext page

A Gekko matrix contains two-dimensional 'cells' with numeric values. Matrix names always start with the symbol #, like the other collection types list and map, and a matrix definition could for instance be #= [1, 2; 3, 4]; for a 2 x 2 matrix. Matrices can be manipulated with the usual linear algebra operators and functions, like adding, multiplying, inverting, etc. See the list of matrix functions in the end of this help page.

 

You may transfer matrices to/from Excel, but only if the Excel cells are numerical values. In general, if you need to manipulate data 'cells' of non-numeric values (like for instance an Excel spreadsheet with cells of values, dates and strings), you should use a nested list instead of a matrix. Nested lists can be of any dimension, and indexing, selecting, looping etc. works similarly for nested lists and matrices. See the SHEET statement if you need to transfer Excel cells into a matrix or nested list.

 


 

Syntax

 

#m = expression;
#m < ROWNAMES = #list  COLNAMES = #list > = expression;

matrix ?; //show/count matrices in open databanks

 

Note: You may use the non-mandatory matrix keyword to indicate matrix type (like matrix #= #+ #z;).

 

ROWNAMES =

A list containing the names (labels) of the rows of the matrix, to be shown with PRT. You may use quotes (') when creating the list elements, if you need special characters like blanks etc.

COLNAMES =

A list containing the names (labels) of the cols of the matrix, to be shown with PRT. You may use quotes (') when creating the list elements, if you need special characters like blanks etc.

name

The name of the matrix, starts with #.

expression

Any expression. You may omit the expression if you just need to decorate an already existing matrix with row- or colnames.

?

Query regarding a particular matrix, or all matrices

 

Note to Excel users: to import data from a spreadsheet, use the SHEET statement (sheet<import matrix>). To export a matrix #m from Gekko to Excel, you can use export <xlsx> #m file = matrix.xlsx;.

 


 

Examples

 

Gekko supports quite a lot of the more common matrix capabilities. More capabilities may be added over time. Regarding matrix functions, please consult the Gekko functions page, under the 'Matrix functions' section (for instance determinant, inverse, transpose, diagonal, summation, etc.). These functions are also shown at the end of this help page.

 

You may construct a 2 x 2 matrix like this:

 

#= [1, 2; 3, 4];

 

The commas , separate the row items, and the ; separates columns. To construct matrices, you may use values or other matrices instead of the fixed numbers shown here. Use PRT to print out a matrix:

 

prt #m;
 
//      #m
//                       1                2 
//      1           1.0000           2.0000 
//      2           3.0000           4.0000

 

Note: after printng a matrix like this, you may use Copy-button in the main Gekko window to copy/paste the matrix to Excel. To decorate with custom row- and col-names, you may do the following (you may alternatively use listfiles to contain the labels, cf. LIST):

 

#rn = ('Agriculture', 'Services etc.');
#cn = ('Employed', 'Unemployed');
#<rownames=#rn colnames=#cn> = [1, 2; 3, 4];
prt #m;
 
// #m
//                      Employed     Unemployed 
//  Agriculture           1.0000         2.0000 
//  Services etc.         3.0000         4.0000

 

You may concatenate existing matrices like this:

 

#= [#m1; #m2];               //column-wise
#= [#m1, #m2];               //row-wise
#= [#m1, #m2; #m3 ,#m4];     //both

 

You may construct matrices filled with 0's, 1's or missing values by means of the functions zeros(n, k), ones(n, k), or miss(n, k), for instance:

 

#= zeros(5, 10);

 

You can use +, -, * and / on two matrices, to add, subtract, multiply or divide. Regarding division, you can only divide a matrix by a value or a 1 x 1 matrix. Otherwise, use the element-by-element functions multiply() and divide().

 

You may index a matrix by means of the indexer []. For instance:

 

%= #m[2, 4];

 

This picks out the element in row 2, column 4. Please note that the indexes are 1-based. The inverse operation:

 

#m[2, 4] = %v;

 

Sub-matrices can be picked out by means of the range dots (..), for instance:

 

#m2 = #m[1..2, 5..7];

 

This picks out rows 1 and 2, and combines them with columns 5, 6 and 7. Note that these ranges may not be descending, for instance #m[2..1, 7..5]. The inverse operation:

 

#m[1..2, 5..7] = #m2;

 

To select a full row or column, use an 'empty' range like this.

 

#m2 = #m[3, ..];

 

This selects all the items in row 3. You may also use for instance 2.. to pick out the elements from 2 and onwards, or ..10 to pick out the elements from 1 up to and including 10. Use .. to pick out all rows/columns.

 

For a column vector #c (that is, a n x 1 matrix), you may omit the column index, so in that case, these two will amount to the same:

 

%= #c[5];
%= #c[5, 1];

 

You may pack and unpack matrices from timeseries, for instance:

 

time 2001 2003;
x1 = 1, 2, 3; 
x2 = 3, 4, 5;
#= pack(2001, 2003,x1, x2);

#m;
y1 = #m[.., 1].unpack(2001, 2003);
y2 = #m[.., 2].unpack(2001, 2003);
<n> x1, y1, x2, y2;

 

This will pack the two timeseries x1 and x2 into a 3 x 2 matrix #m (with data from 2001-2003). You may unpack back into two timeseries again with the unpack() function as shown. The indexes [.., 1] and [.., 2] pick out all rows of the two columns in #m. You may also consult the pack/unpack example in the R_RUN section. Column vectors can be handy, when you use them as a list of values:

 

#= [100; 150; 120];
for val %= 1 to #m.rows();
  tell 'Index {%i} has value {#m[%i]}';
end;
 
// Index 1 has value 100
// Index 2 has value 150
// Index 3 has value 120

 

Since #m is a column vector, you may use #m[%i] instead of the more cumbersome #m[%i, 1].

 

There are min(), max(), avg() and sum() functions, working on rows or columns. For instance, you may decorate a matrix with grand totals like in the code below (where the third row and column are totals). The functions sumr() and sumc() sum the rows and columns, respectively. The last expression, #m.sumc().sumr(), could just as well have been stated as #m.sumr().sumc(). The divide(#m1, #m2) function divides two matrices element by element, but #m2 may have only 1 row or column stated. In that case, the function works on rows or columns, respectively.

 

#= [1, 2; 3, 4];
prt [#m, #m.sumr(); #m.sumc(), #m.sumc().sumr()];
prt divide(#m, #m.sumr());
prt divide(#m, #m.sumc());
 
// [#m, #m.sumr(); #m.sumc(), #m.sumc().sumr()]
//                    1              2              3 
//     1         1.0000         2.0000         3.0000 
//     2         3.0000         4.0000         7.0000 
//     3         4.0000         6.0000        10.0000 
// 
// divide(#m, #m.sumr())
//                    1              2 
//     1         0.3333         0.6667 
//     2         0.4286         0.5714 
// 
// divide(#m, #m.sumc())
//                    1              2 
//     1         0.2500         0.3333 
//     2         0.7500         0.6667 

 

In the first print, the rows sum to 1, and in the second print, the columns sum to 1. Matrices can be exported and imported from Excel, for instance:

 

#= [1, 2, 3; 4, 5, 6];
export <xlsx> #m file = m.xlsx;
sheet <import matrix> #m2 file=m.xlsx;
prt #m, #m2;

 

The example below estimates a linear least squares model with five parameters. You may consult the OLS section to see the same parameters calculated via the OLS solver, or the R_RUN section to see the same parameters calculated via the R interface.

 

reset;
lna1 <1998 2010> = data(' 166.223000  173.221000  179.571000  187.343000  194.888000  202.959000  
209.426000  215.134000  222.716000  230.520000  238.518000  246.654000  254.991000') ;
pcp <1998 2010>   = data(' 0.9502030   0.9699920   1.0000000   1.0235000   1.0401100   1.0605400   
1.0754700   1.0977800   1.1121200   1.1314800   1.1513000   1.1717600   1.1871600')  ;
bul1 <1998 2010>  = data(' 0.0684791   0.0591698   0.0560344   0.0535439   0.0535003   0.0631703   
0.0649875   0.0578112   0.0473207   0.0404508   0.0467488   0.0472923   0.0475191')  ;
time 2000 2010;
s0 = dlog(lna1);
s1 = dlog(pcp);
s2 = dlog(pcp.1);
s3 = bul1;
s4 = bul1.1;
s5 = 1;
#= pack(2000, 2010, s1, s2, s3, s4, s5);
#= pack(2000, 2010, s0);
#= inv(t(#x)*#x)*t(#x)*#y;  //OLS formula
prt #b; //parameter estimates
 
//                    1 
//     1         0.1445 
//     2         0.6139 
//     3         0.1867 
//     4        -0.3509 
//     5         0.0298 

 

You may see a list of all matrices with:

 

matrix ?;

 

 


 

Matrix functions

 

Matrix functions:

 

Function name

Description

Examples

avgc(x)

Average over cols for the matrix x.

Returns: matrix

#m2 = avgc(#m1);

avgr(x)

Average over rows for the matrix x.

Returns: matrix

#m2 = avgr(#m1);

chol(x)

chol(x, type)

Cholesky decomposition of matrix x. Accepts type (string), either 'upper' or 'lower'.

Returns: matrix

#m2 = chol(#m1, 'upper');

cols(x)

Returns the number of colums of the matrix x.

Returns: val

%= cols(#m);

design(x)

Returns a "design" matrix given the input matrix x, equivalent to the same Gauss function. The function is practical for aggregating rows or columns.

 

Input: is a n x 1 column matrix.

Returns: n x k matrix of 0's and 1's. The input numbers specify the columns in which the 1's should be placed.

 

In the example, a 4 x 5 matrix #x of 1's is defined, and by means of the aggregation matrix #m, it is aggregated from size 4 x 5 to 4 x 3. In this case, the new column 1 is the old columns 2 and 3, the new column 2 is the old column 5, and the new column 3 is the old columns 1 and 4.

#= [3; 1; 1; 3; 2];
#= design(#a);
#= ones(4, 5);
#m, #* #d;
 
#m
                   1              2              3 
    1         0.0000         0.0000         1.0000 
    2         1.0000         0.0000         0.0000 
    3         1.0000         0.0000         0.0000 
    4         0.0000         0.0000         1.0000 
    5         0.0000         1.0000         0.0000 
 
#* #d
                   1              2              3 
    1         2.0000         1.0000         2.0000 
    2         2.0000         1.0000         2.0000 
    3         2.0000         1.0000         2.0000 
    4         2.0000         1.0000         2.0000 

det(x)

Determinant of a matrix x.

Returns: val

%= det(#m);

diag(x)

Diagonal. If x is a n x n symmetric matrix, the method returns the diagonal as a n x 1 matrix. If x is a n x 1 column vector, the method returns a n x n matrix with this column vector on the diagonal (and zeroes elsewhere).

Returns: matrix

#m2 = diag(#m1);

divide(x1, x2)

Element by element division of the two matrices x1 and x2. If x2 is a row vector, each x1 column will be divided with the corresponding value from the row vector.  And if x2 is a column vector, each x1 row will be divided with the corresponding value from the column vector.

Returns: matrix

#= divide(#x1, #x2);

i(n)

Returns a n x n identity matrix.

Returns: matrix

#= i(10);

inv(x)

Inverse of matrix x.

Returns: matrix

#m2 = inv(#m1);

maxc(x)

Max over cols of matrix x.

Returns: matrix

#m2 = maxc(#m1);

maxr(x)

Max over rows of matrix x.

Returns: matrix

#m2 = maxr(#m1);

minc(x)

Min over cols of matrix x.

Returns: matrix

#m2 = minc(#m1);

minr(x)

Min over rows of matrix x.

Returns: matrix

#m2 = minr(#m1);

m(n, k) or miss(n, k)

Returns a n x k matrix filled with missing values. Cf. also m() function for values.

Returns: matrix

#= m(5, 10);

multiply(x1, x2)

Element by element multiplication of the two matrices x1 and x2. If x2 is a row vector, each x1 column will be multiplied with the corresponding value from the row vector.  And if x2 is a column vector, each x1 row will be multiplied with the corresponding value from the column vector.

Returns: matrix

#= multiply(#x1, #x2);

ones(n, k)

Returns a n x k matrix filled with 1's

Returns: matrix

#= ones(5, 10);

pack(v1, v2, ...)

pack(<t1 t2>, v1, v2, ...)

Using period t1 to t2, the timeseries v1, v2, ... are packed into a n x k matrix, where n is the number of observations and k is the number of variables. If the period is omitted, the global time period is used.

Returns: matrix

#= pack(<2020 2030>, x, y, z); Returns: a 11 x 3 matrix #m with the values.

rows(x)

Returns the number of rows of the matrix x.

Returns: val

%= rows(#m);

sumc(x)

Sum over cols of the matrix x.

Returns: matrix

#m2 = sumc(#m1);

sumr(x)

Sum over rows of the matrix x.

Returns: matrix

#m2 = sumr(#m1);

t(x)

Returns the transpose of a matrix x.

Returns: matrix

#m2 = t(#m1);

trace(x)

Returns the trace of a matrix x. (This does not have anything to do with data-traces).

Returns: val

%= trace(#m);

unpack(m)

unpack(<t1 t2>, m)

The column matrix m (with only one column) is unpacked into a timeseries spanning the period t1 to t2. If the period is omitted, the local/global time period is used.

The unpack() function is not strictly necessary: you may alternatively assign a n x 1 matrix directly to a series (see example).

Returns: series

//This picks out the second column of #m (and all the rows).

= #m[.., 2].unpack(<2020 2030>);  
<2020 2030> = #m[.., 2].unpack();  //same
<2020 2030> = #m[.., 2]; //also works

zeros(n, k)

zeroes(n, k)

Returns a n x k matrix filled with 0's. Zeroes() can be used as alias.

Returns: matrix

#= zeros(5, 10);

 

 


 

Notes

 

See the page with syntax diagrams if the basics of names, expressions, etc. is confusing.

 

You may use m() to indicate a missing value for a matrix element. You can also use m(2, 3) to get a 2 x 3 matrix with missing values.

 

Note that an assignment like #m1 = #m2;, where #m2 is a matrix, #m1 will become a copy of #m2, not a reference to it. The same is the case regarding function arguments, where manipulating #m1 inside the function body of f(#m1) will not affect #m1 after the function has been left.

 

Regarding variable types and the Gekko type system, see the VAR section. In this appendix, variable assignment rules, including variable types, is explained in more detail.

 

A Gekko matrix only supports numeric values inside the cells. It relates to the following in different languages:

 

Gekko: #m= [1, 2; 3, 4];

R: matrix data structure, = matrix(c(1, 2, 3, 4), nrow=2, ncol=2)

Python: list of lists (with numeric values), = [[1, 2], [3, 4]]

Matlab: two-dimensional array of numeric values

 


 

Related statements

 

LIST, SERIES, SHEET, VAL