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

Convert a matrix to a vector by function reshape or flatten

m1=1..6$3:2;
m2 = m1$2:3;
m2;
#0 #1 #2
1 3 5
2 4 6
m=(1..6).reshape(3:2);
m;
#0 #1
1 4
2 5
3 6
y=m.reshape()
y;
// output
[1,2,3,4,5,6]

flatten m;
// output
[1,2,3,4,5,6]

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
5

There 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
10

There 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 MATRIX

There 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