Matrix
A matrix in DolphinDB is implemented by a one-dimensional array with column major. Please note that both the column index and the row index start from 0.
Creating matrices
Use function matrix to create a matrix:
// create an integer matrix with all values set to the default value of 0
matrix(int, 2, 3);| #0 | #1 | #2 | 
|---|---|---|
| 0 | 0 | 0 | 
| 0 | 0 | 0 | 
// create a symbol matrix with all values set to the default value of null
matrix(symbol, 2, 3);| #0 | #1 | #2 | 
|---|---|---|
The matrix function can also create a matrix from vectors, matrices, table, tuple of vectors and their combination.
matrix(1 2 3);| #0 | 
|---|
| 1 | 
| 2 | 
| 3 | 
matrix([1],[2])| #0 | #1 | 
|---|---|
| 1 | 2 | 
matrix(1 2 3, 4 5 6);| #0 | #1 | 
|---|---|
| 1 | 4 | 
| 2 | 5 | 
| 3 | 6 | 
matrix(table(1 2 3 as id, 4 5 6 as value));| #0 | #1 | 
|---|---|
| 1 | 4 | 
| 2 | 5 | 
| 3 | 6 | 
matrix([1 2 3, 4 5 6]);| #0 | #1 | 
|---|---|
| 1 | 4 | 
| 2 | 5 | 
| 3 | 6 | 
matrix([1 2 3, 4 5 6], 7 8 9);| #0 | #1 | #2 | 
|---|---|---|
| 1 | 4 | 7 | 
| 2 | 5 | 8 | 
| 3 | 6 | 9 | 
matrix([1 2 3, 4 5 6], 7 8 9, table(0.5 0.6 0.7 as id), 1..9$3:3);| #0 | #1 | #2 | #3 | #4 | #5 | #6 | 
|---|---|---|---|---|---|---|
| 1 | 4 | 7 | 0.5 | 1 | 4 | 7 | 
| 2 | 5 | 8 | 0.6 | 2 | 5 | 8 | 
| 3 | 6 | 9 | 0.7 | 3 | 6 | 9 | 
Statement X $ m:n or function cast(X, m:n) converts vector X into an m by n matrix.
m=1..10$5:2;
m;| #0 | #1 | 
|---|---|
| 1 | 6 | 
| 2 | 7 | 
| 3 | 8 | 
| 4 | 9 | 
| 5 | 10 | 
cast(m,2:5);| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 3 | 5 | 7 | 9 | 
| 2 | 4 | 6 | 8 | 10 | 
DolphinDB is a column major system. Consecutive elements of columns are contiguous in memory. DolphinDB fills the elements in a matrix along the columns from the left to the right.
Use function rename! to add column names or row names to a matrix:
m1=1..9$3:3;
m1;| #0 | #1 | #2 | 
|---|---|---|
| 1 | 4 | 7 | 
| 2 | 5 | 8 | 
| 3 | 6 | 9 | 
m1.rename!(`col1`col2`col3);| col1 | col2 | col3 | 
|---|---|---|
| 1 | 4 | 7 | 
| 2 | 5 | 8 | 
| 3 | 6 | 9 | 
m1.rename!(1 2 3, `c1`c2`c3);| c1 | c2 | c3 | 
|---|---|---|
| 1 | 4 | 7 | 
| 2 | 5 | 8 | 
| 3 | 6 | 9 | 
m1.colNames();
// output: ["c1","c2","c3"]
m1.rowNames();
// output: [1,2,3]Reshaping matrices
Accessing matrices
Check dimensions ( shape), the number of rows( rows)and the number of columns ( cols):
m=1..10$2:5;
shape m;
// output: 2 : 5
rows m
// output: 2
cols m
// output: 5There are 2 ways to retrieve a cell: m.cell(row, col) or m[row, col].
m=1..12$4:3;
m;| #0 | #1 | #2 | 
|---|---|---|
| 1 | 5 | 9 | 
| 2 | 6 | 10 | 
| 3 | 7 | 11 | 
| 4 | 8 | 12 | 
m[1,2];
// output: 10
m.cell(1,2);
// output: 10There are 2 ways to retrieve columns: m.col(index) where index is scalar/pair, and m[index] or m[, index] where index is scalar/pair/vector.
m=1..12$4:3;
m;| #0 | #1 | #2 | 
|---|---|---|
| 1 | 5 | 9 | 
| 2 | 6 | 10 | 
| 3 | 7 | 11 | 
| 4 | 8 | 12 | 
m[1];
// output: [5,6,7,8]
// select the column at position 1 to produce a vector
m[,1];
// select the column at position 1 to produce a sub matrix| #1 | 
|---|
| 5 | 
| 6 | 
| 7 | 
| 8 | 
m.col(2);
// output: [9,10,11,12]
// select the column at position 2
m[2:0];
// select the columns at position 1 and 0| #0 | #1 | 
|---|---|
| 5 | 1 | 
| 6 | 2 | 
| 7 | 3 | 
| 8 | 4 | 
m[1:3];
// select the columns at position 1 and 2| #0 | #1 | 
|---|---|
| 5 | 9 | 
| 6 | 10 | 
| 7 | 11 | 
| 8 | 12 | 
Please note that if index is a scalar, both m.col(index) and m[index] generate a vector whereas m[, index] generates a matrix.
m.col(1).typestr();
// output: FAST INT VECTOR
m[1].typestr();
// output: FAST INT VECTOR
m[,1].typestr();
// output: FAST INT MATRIXThere are 2 ways to retrieve rows: m.row(index) where index is scalar/pair, and m[index,] where index is scalar/pair/vector.
m=1..12$3:4;
m;| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 1 | 4 | 7 | 10 | 
| 2 | 5 | 8 | 11 | 
| 3 | 6 | 9 | 12 | 
m[0,];
// return a sub matrix with row 0| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 1 | 4 | 7 | 10 | 
// use function flatten to convert a matrix to a vector
flatten(m[0,]);
// output: [1,4,7,10]
// select row 2
m.row(2);
// output: [3,6,9,12]
// select rows 1 and 2.
m[1:3, ];| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 2 | 5 | 8 | 11 | 
| 3 | 6 | 9 | 12 | 
m[3:1, ];| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 3 | 6 | 9 | 12 | 
| 2 | 5 | 8 | 11 | 
There are 2 ways to retrieve a submatrix: m.slice(rowIndexRange,colIndexRange) and m[rowIndexRange,colIndexRange] where colIndex and rowIndex is scalar/pair. The upper bound is exclusive.
m=1..12$3:4;
m;| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 1 | 4 | 7 | 10 | 
| 2 | 5 | 8 | 11 | 
| 3 | 6 | 9 | 12 | 
m.slice(0:2,1:3);| #0 | #1 | 
|---|---|
| 4 | 7 | 
| 5 | 8 | 
m[1:3,0:2];
// select rows 1 and 2, columns 0 and 1.| #0 | #1 | 
|---|---|
| 2 | 5 | 
| 3 | 6 | 
m[1:3,2:0];
// select rows 1 and 2, columns 1 and 0.| #0 | #1 | 
|---|---|
| 5 | 2 | 
| 6 | 3 | 
m[3:1,2:0];
// select rows 2 and 1, columns 1 and 0.| #0 | #1 | 
|---|---|
| 6 | 3 | 
| 5 | 2 | 
Modifying matrices
To append a matrix with a vector, the vector's size must be a multiple of the number of the rows of the matrix.
m=1..6$2:3;
m;| #0 | #1 | #2 | 
|---|---|---|
| 1 | 3 | 5 | 
| 2 | 4 | 6 | 
append!(m, 7 9);| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 1 | 3 | 5 | 7 | 
| 2 | 4 | 6 | 9 | 
append!(m, 8 6 1 2);
// appending m with two columns| #0 | #1 | #2 | #3 | #4 | #5 | 
|---|---|---|---|---|---|
| 1 | 3 | 5 | 7 | 8 | 1 | 
| 2 | 4 | 6 | 9 | 6 | 2 | 
append!(m, 3 4 5);
// output: The size of the vector to append must be divisible by the number of matrix rows.Starting from version 2.00.4, you can use m[condition] = X for conditional assignment on a matrix, where condition is a Boolean matrix with the same shape as m. X is a scalar or vector. When X is a vector, the length must be the same as the number of true values in condition.
a = 1..12$3:4
a[a<5]=5| #0 | #1 | #2 | #3 | 
|---|---|---|---|
| 5 | 5 | 7 | 10 | 
| 5 | 5 | 8 | 11 | 
| 5 | 6 | 9 | 12 | 
To modify a column, use m[index]=X where X is a scalar/vector.
t1=1..50$10:5;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 2 | 12 | 22 | 32 | 42 | 
| 3 | 13 | 23 | 33 | 43 | 
| 4 | 14 | 24 | 34 | 44 | 
| 5 | 15 | 25 | 35 | 45 | 
| 6 | 16 | 26 | 36 | 46 | 
| 7 | 17 | 27 | 37 | 47 | 
| 8 | 18 | 28 | 38 | 48 | 
| 9 | 19 | 29 | 39 | 49 | 
| 10 | 20 | 30 | 40 | 50 | 
// assign 200 to column 1
t1[1]=200;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 200 | 21 | 31 | 41 | 
| 2 | 200 | 22 | 32 | 42 | 
| 3 | 200 | 23 | 33 | 43 | 
| ... | ... | ... | ... | ... | 
// add 200 to column 1
t1[1]+=200;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 400 | 21 | 31 | 41 | 
| 2 | 400 | 22 | 32 | 42 | 
| 3 | 400 | 23 | 33 | 43 | 
| ... | ... | ... | ... | ... | 
// assign sequence 31..40 to column 1
t1[1]=31..40;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 31 | 21 | 31 | 41 | 
| 2 | 32 | 22 | 32 | 42 | 
| 3 | 33 | 23 | 33 | 43 | 
| ... | ... | ... | ... | ... | 
To modify multiple columns, use m[start:end] = X, where X is a scalar or vector.
t1=1..50$10:5;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 2 | 12 | 22 | 32 | 42 | 
| 3 | 13 | 23 | 33 | 43 | 
| 4 | 14 | 24 | 34 | 44 | 
| 5 | 15 | 25 | 35 | 45 | 
| 6 | 16 | 26 | 36 | 46 | 
| 7 | 17 | 27 | 37 | 47 | 
| 8 | 18 | 28 | 38 | 48 | 
| 9 | 19 | 29 | 39 | 49 | 
| 10 | 20 | 30 | 40 | 50 | 
// assign sequence 101..130 to columns 1,2,3
t1[1:4]=101..130;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 101 | 111 | 121 | 41 | 
| 2 | 102 | 112 | 122 | 42 | 
| 3 | 103 | 113 | 123 | 43 | 
| ... | ... | ... | ... | ... | 
// assign sequence 101..130 to columns 3,2,1
t1[4:1]=101..130;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 121 | 111 | 101 | 41 | 
| 2 | 122 | 112 | 102 | 42 | 
| 3 | 123 | 113 | 103 | 43 | 
| ... | ... | ... | ... | ... | 
// add 100 to columns 3,2,1
t1[4:1]+=100;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 221 | 211 | 201 | 41 | 
| 2 | 222 | 212 | 202 | 42 | 
| 3 | 223 | 213 | 203 | 43 | 
| ... | ... | ... | ... | ... | 
To modify a row, use m[index,] = X, where X is a scalar/vector.
t1=1..50$10:5;
// assign 100 to row 1
t1[1,]=100;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 100 | 100 | 100 | 100 | 100 | 
| 3 | 13 | 23 | 33 | 43 | 
| ... | ... | ... | ... | ... | 
// add 100 to row 1
t1[1,]+=100;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 200 | 200 | 200 | 200 | 200 | 
| 3 | 13 | 23 | 33 | 43 | 
| ... | ... | ... | ... | ... | 
To modify multiple rows, use m[start:end,] = X, where X is a scalar/vector.
t1=1..50$10:5;
// assign sequence 101..115 to columns 1 to 3
t1[1:4,]=101..115;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 101 | 104 | 107 | 110 | 113 | 
| 102 | 105 | 108 | 111 | 114 | 
| 103 | 106 | 109 | 112 | 115 | 
| ... | ... | ... | ... | ... | 
// assign sequence 101..115 to columns 3 to 1
t1[4:1, ]=101..115;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 103 | 106 | 109 | 112 | 115 | 
| 102 | 105 | 108 | 111 | 114 | 
| 101 | 104 | 107 | 110 | 113 | 
| ... | ... | ... | ... | ... | 
To modify an area in a matrix, use m[r1:r2, c1:c2] = X, where X is a scalar/vector.
t1=1..50$5:10;
//assign sequence 101..110 to the matrix window of row 1~2 and column 5~9
t1[1:3,5:10]=101..110;
t1;| #0 | #1 | #2 | #3 | #4 | #5 | #6 | #7 | #8 | #9 | 
|---|---|---|---|---|---|---|---|---|---|
| 1 | 6 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 
| 2 | 7 | 12 | 17 | 22 | 101 | 103 | 105 | 107 | 109 | 
| 3 | 8 | 13 | 18 | 23 | 102 | 104 | 106 | 108 | 110 | 
| 4 | 9 | 14 | 19 | 24 | 29 | 34 | 39 | 44 | 49 | 
| 5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 
t1=1..50$10:5;
// assign sequence 101..110 to the matrix window of row 5~9 and column 2~1
t1[5:10, 3:1]=101..110;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| ... | ... | ... | ... | ... | 
| 6 | 106 | 101 | 36 | 46 | 
| 7 | 107 | 102 | 37 | 47 | 
| 8 | 108 | 103 | 38 | 48 | 
| 9 | 109 | 104 | 39 | 49 | 
| 10 | 110 | 105 | 40 | 50 | 
// add 10 to the matrix window of rows 9~5 and columns 1~2
t1[10:5, 1:3]+=10;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1 | 11 | 21 | 31 | 41 | 
| 2 | 12 | 22 | 32 | 42 | 
| 3 | 13 | 23 | 33 | 43 | 
| 4 | 14 | 24 | 34 | 44 | 
| 5 | 15 | 25 | 35 | 45 | 
| 6 | 116 | 111 | 36 | 46 | 
| 7 | 117 | 112 | 37 | 47 | 
| 8 | 118 | 113 | 38 | 48 | 
| 9 | 119 | 114 | 39 | 49 | 
| 10 | 120 | 115 | 40 | 50 | 
To update on specified elements of a matrix, use m[rowIndex,colIndex] = X, where rowIndex, colIndex and X can be a scalar/vector.
t1=1..20$4:5
t1[0 2, 0 2]=101;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 101 | 5 | 101 | 13 | 17 | 
| 2 | 6 | 10 | 14 | 18 | 
| 101 | 7 | 101 | 15 | 19 | 
| 4 | 8 | 12 | 16 | 20 | 
t1[2 0, 2 0]=1001..1004;
t1;| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 1004 | 5 | 1002 | 13 | 17 | 
| 2 | 6 | 10 | 14 | 18 | 
| 1003 | 7 | 1001 | 15 | 19 | 
| 4 | 8 | 12 | 16 | 20 | 
Removing certain columns of a matrix
We can use lambda expressions to remove certain columns of a matrix. Please note that for this usage the lambda expression can only accept one parameter, and the result must be a Boolean type scalar.
m=matrix(0 2 3 4,0 0 0 0,4 7 8 2);
m[x->!all(x==0)];
// return the columns that are not all 0s.| #0 | #1 | 
|---|---|
| 0 | 4 | 
| 2 | 7 | 
| 3 | 8 | 
| 4 | 2 | 
m=matrix(0 2 3 4,5 3 6 9,4 7 8 2);
m[def (x):avg(x)>4];
// return the columns with average value greater than 4.| #0 | #1 | 
|---|---|
| 5 | 4 | 
| 3 | 7 | 
| 6 | 8 | 
| 9 | 2 | 
Operating on matrices
Operations between a matrix and a scalar:
m=1..10$5:2;
m;| #0 | #1 | 
|---|---|
| 1 | 6 | 
| 2 | 7 | 
| 3 | 8 | 
| 4 | 9 | 
| 5 | 10 | 
2.1*m;
// multiply 2.1 with each element in the matrix| #0 | #1 | 
|---|---|
| 2.1 | 12.6 | 
| 4.2 | 14.7 | 
| 6.3 | 16.8 | 
| 8.4 | 18.9 | 
| 10.5 | 21 | 
m\2;| #0 | #1 | 
|---|---|
| 0.5 | 3 | 
| 1 | 3.5 | 
| 1.5 | 4 | 
| 2 | 4.5 | 
| 2.5 | 5 | 
m+1.1;| #0 | #1 | 
|---|---|
| 2.1 | 7.1 | 
| 3.1 | 8.1 | 
| 4.1 | 9.1 | 
| 5.1 | 10.1 | 
| 6.1 | 11.1 | 
m*NULL;
// the result is a null INT matrix| #0 | #1 | 
|---|---|
Operations between a matrix and a vector:
m=matrix(1 2 3, 4 5 6);
m;| #0 | #1 | 
|---|---|
| 1 | 4 | 
| 2 | 5 | 
| 3 | 6 | 
m + 10 20 30;| #0 | #1 | 
|---|---|
| 11 | 14 | 
| 22 | 25 | 
| 33 | 36 | 
m * 10 20 30;| #0 | #1 | 
|---|---|
| 10 | 40 | 
| 40 | 100 | 
| 90 | 180 | 
Operations between matrices:
m1=1..10$2:5
m2=11..20$2:5;
m1+m2;
// element-wise addition| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 12 | 16 | 20 | 24 | 28 | 
| 14 | 18 | 22 | 26 | 30 | 
m1-m2;
// element-wise substract| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| -10 | -10 | -10 | -10 | -10 | 
| -10 | -10 | -10 | -10 | -10 | 
m1*m2;
// element-wise multiplication| #0 | #1 | #2 | #3 | #4 | 
|---|---|---|---|---|
| 11 | 39 | 75 | 119 | 171 | 
| 24 | 56 | 96 | 144 | 200 | 
m2 = transpose(m2);
m1**m2;
// matrix multiplication| #0 | #1 | 
|---|---|
| 415 | 440 | 
| 490 | 520 | 
Applying functions to matrices
Matrix is a special case of vector. Therefore most vector functions can be applied to matrices.
m=1..6$2:3;
m;| #0 | #1 | #2 | 
|---|---|---|
| 1 | 3 | 5 | 
| 2 | 4 | 6 | 
// average of each row
avg(m);
// output: [1.5,3.5,5.5]
// sum of each row
sum(m);
// output: [3,7,11]
// cosine of each element
cos m;| #0 | #1 | #2 | 
|---|---|---|
| 0.540302 | -0.989992 | 0.283662 | 
| -0.416147 | -0.653644 | 0.96017 | 
To perform calculations on each column of a matrix, we can also use the template each.
Matrix specific functions
We have the following matrix specific functions transpose, inverse(inv), det, diag and solve.
m=1..4$2:2;
transpose m;| #0 | #1 | 
|---|---|
| 1 | 2 | 
| 3 | 4 | 
inv(m);| #0 | #1 | 
|---|---|
| -2 | 1.5 | 
| 1 | -0.5 | 
det(m);
// output: -2// solving m*x=[1,2]
m.solve(1 2);
// output: [1,0]
y=(1 0)$2:1;
y;| #0 | 
|---|
| 1 | 
| 0 | 
m**y;| #0 | 
|---|
| 1 | 
| 2 | 
diag(1 2 3);| #0 | #1 | #2 | 
|---|---|---|
| 1 | 0 | 0 | 
| 0 | 2 | 0 | 
| 0 | 0 | 3 | 
