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:nor 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 |
1 |
4 |
7 |
2 |
2 |
5 |
8 |
3 |
3 |
6 |
9 |
$ m1.colNames();
["c1","c2","c3"]
$ m1.rowNames();
[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;
[1,2,3,4,5,6]
$ flatten m;
[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;
2 : 5
$ rows m
2
$ cols m
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];
10
$ m.cell(1,2);
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];
[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);
[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();
FAST INT VECTOR
$ m[1].typestr();
FAST INT VECTOR
$ m[,1].typestr();
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,]);
[1,4,7,10]
// select row 2
$ m.row(2);
[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);
The size of the vector to append must be divisible by the number of matrix rows.
Starting from version 1.30.16/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..20$4:5;
$ t1;
#0 |
#1 |
#2 |
#3 |
#4 |
---|---|---|---|---|
1 |
5 |
9 |
13 |
17 |
2 |
6 |
10 |
14 |
18 |
3 |
7 |
11 |
15 |
19 |
4 |
8 |
12 |
16 |
20 |
// assign sequence 101..112 to columns 1 to 3
$ t1[0 2 4]=101..112;
$ t1;
#0 |
#1 |
#2 |
#3 |
#4 |
---|---|---|---|---|
101 |
5 |
105 |
13 |
109 |
102 |
6 |
106 |
14 |
110 |
103 |
7 |
107 |
15 |
111 |
104 |
8 |
108 |
16 |
112 |
… |
// assign sequence 101..112 to columns 4,2,0
$ t1[4 2 0]=101..112;
$ t1;
#0 |
#1 |
#2 |
#3 |
#4 |
---|---|---|---|---|
109 |
5 |
105 |
13 |
101 |
110 |
6 |
106 |
14 |
102 |
111 |
7 |
107 |
15 |
103 |
112 |
8 |
108 |
16 |
104 |
… |
// add 100 to columns 4,2,0
$ t1[4 2 0]+=100;
$ t1;
#0 |
#1 |
#2 |
#3 |
#4 |
---|---|---|---|---|
209 |
5 |
205 |
13 |
201 |
210 |
6 |
206 |
14 |
202 |
211 |
7 |
207 |
15 |
203 |
212 |
8 |
208 |
16 |
204 |
… |
To modify a row, 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 101..130 to row 1 to 4
$ 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 |
… |
To modify multiple rows, use m[start:end,] = X, where X is a scalar/vector.
$ t1=1..50$10:5;
$ 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 columns3 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;
//To modify an area in a matrix, use m[r1:r2, c1:c2] = X, where X is a scalar/vector.
$ 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 addition
#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 |
$ avg(m);
// average of each row
[1.5,3.5,5.5]
$ sum(m);
// sum of each row
[3,7,11]
$ 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);
-2
$ m.solve(1 2);
// solving m*x=[1,2]
[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 |