矩阵

DolphinDB 矩阵中的每一列都是一维数组。矩阵中行和列的下标都是从0开始。

创建矩阵

用函数 matrix 创建一个矩阵

// 创建一个整数矩阵,所有值都设为默认值0。
matrix(INT, 2, 3);
#0 #1 #2
0 0 0
0 0 0
// 创建一个 SYMBOL 矩阵,所有值都设为默认值 NULL
matrix(SYMBOL, 2, 3);
#0 #1 #2

函数 matrix 可以创建包含向量、矩阵、表、元组及这些数据组合的混合数据的矩阵。

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

函数 cast(X, m:n) 把一个向量X转换为一个m×n的矩阵。

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

用函数 setIndexedMatrix! 可以将矩阵的行与列标签设为索引,即生成一个索引矩阵。

m = matrix(1..5, 6..10);
m.rename!(2021.01.01..2021.01.05, `A`B);
m.setIndexedMatrix!();

输出返回:

label A B
2021.01.01 1 6
2021.01.02 2 7
2021.01.03 3 8
2021.01.04 4 9
2021.01.05 5 10

函数 indexedSeries 创建一个索引序列,可以视为特殊的矩阵。

m = indexedSeries(2012.01.01..2012.01.04, [10, 20, 30, 40]);
m;
label col1
2012.01.01 10
2012.01.02 20
2012.01.03 30
2012.01.04 40

DolphinDB 是列式数据库系统,在内存中以列为单位连续储存数据。DolphinDB 从左向右以列为单位填充矩阵中的元素。

使用 rename! 函数给矩阵增加行标签和列标签。

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);
1 1 4 7
2 2 5 8
3 3 6 9
m1.colNames();

["c1","c2","c3"]

m1.rowNames();

[1,2,3]

重新排列矩阵

用函数 reshapeflatten 把一个矩阵转换为一个向量。

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]

访问矩阵

检查维度 ( shape),行数( rows)和列数 ( cols):

m=1..10$2:5;
shape m;

2 : 5

rows m

2
cols m

5

有两种获得某个单元格的值的方式:m.cell(row, col) 和 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

有两种取得某一列的值的方式:第一种是 m.col(index),其中 index 可以是数据对或者标量;第二种是 m[index] 或 m[, index],其中 index 可以是标量、数据对或者是向量。

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]
// 选出第1列生成一个向量。

m[,1];
// 选出第1列生成一个子矩阵。
#0
5
6
7
8
m.col(2);

[9,10,11,12]
// 选出第2列。

m[2:0];
// 选出第0,1列。
#0 #1
5 1
6 2
7 3
8 4
m[1:3];
// 选出第1,2列。
#0 #1
5 9
6 10
7 11
8 12
m[0 2];
//选出第0列和第2列。
#0 #1
1 9
2 10
3 11
4 12

有两种取得某一行的值的方式:第一种是 m.row(index) ,其中 index 可以是数据对或者标量;第二种是 m[index, ],其中 index 可以是标量、数据对或者是向量。

m=1..12$3:4;
m;
#0 #1 #2 #3
1 4 7 10
2 5 8 11
3 6 9 12
m[0,];
// 返回第0行,类型为矩阵。
#0 #1 #2 #3
1 4 7 10
flatten(m[0,]);
// 用 flatten 函数将一个矩阵转化为向量。

[1,4,7,10]

m.row(2);
// 选出第2行。

[3,6,9,12]

m[1:3, ];
// 选出第1,2行。
#0 #1 #2 #3
2 5 8 11
3 6 9 12
m[3:1, ];
// 选出第2,1行。
#0 #1 #2 #3
3 6 9 12
2 5 8 11
m[0 2,0..3];
//选出第0行和第2行。
#0 #1 #2 #3
1 4 7 10
3 6 9 12

有两种取得子矩阵的方式:第一种是 m.slice(rowIndex,colIndex) 或 m[rowIndex,colIndex],其中collndex 和 rowIndex 是标量、向量或数据对。如果 colIndex 和 rowIndex 是数据对,那么上限边界值不包含在内。

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];
// 选出第1,2行,第0,1列。
#0 #1
2 5
3 6
m[1:3,2:0];
// 选出第1,2行,第1,0列
#0 #1
5 2
6 3
m[3:1,2:0];
// 选出第2,1行,第1,0列
#0 #1
6 3
5 2
m[0 2,1 3];
//选出第0,2行,第1,3列
#0 #1
4 10
6 12
m[2 1,1 3];
//选出第2,1行,第1,3列
#0 #1
6 12
5 11

修改矩阵

当我们追加一个向量到矩阵时,向量的长度必须是矩阵行数的倍数。

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);
// 追加2列到m
#0 #1 #2 #3 #4 #5
1 3 5 7 8 1
2 4 6 9 6 2
append!(m, 3 4 5);
// 要追加的向量长度必须能被矩阵的行数除尽。

2.00.4及之后的版本,支持使用 m[condition]=X 来修改某些符合条件的值。condition 是一个同 m 具有相同维度的布尔矩阵。X 是一个标量或向量,当 X 是向量时,长度必须与 condition 中 true 值的个数相同。

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

使用 m[index]=X 来修改某一列,X 是一个标量或者向量。

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
t1[1]=200;
// 给第1列赋值200
t1;
#0 #1 #2 #3 #4
1 200 21 31 41
2 200 22 32 42
3 200 23 33 43
... ... ... ... ...
t1[1]+=200;
// 给第1列加200
t1;
#0 #1 #2 #3 #4
1 400 21 31 41
2 400 22 32 42
3 400 23 33 43
... ... ... ... ...
t1[1]=31..40;
// 将31..40的序列追加到第1列
t1;
#0 #1 #2 #3 #4
1 31 21 31 41
2 32 22 32 42
3 33 23 33 43
... ... ... ... ...

使用 m[index] = X 来修改多个列,其中 index 是向量,X 是一个标量或者向量。

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
t1[0 2 4]=101..112;
// 将序列101..112 赋值给第0,2,4列
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
... ... ... ... ...
t1[4 2 0]=101..112;
// 将序列101..112赋值给第4,2,0列
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
... ... ... ... ...
t1[4 2 0]+=100;
// 第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
... ... ... ... ...

使用 m[start:end] = X 来修改多个列,X 是一个标量或者向量。

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
t1[1:4]=101..130;
// 追加向量101..130到第1,2,3列
t1;
#0 #1 #2 #3 #4
1 101 111 121 41
2 102 112 122 42
3 103 113 123 43
... ... ... ... ...
t1[4:1]=101..130;
// 追加向量101..130到第3,2,1列
t1;
#0 #1 #2 #3 #4
1 121 111 101 41
2 122 112 102 42
3 123 113 103 43
... ... ... ... ...
t1[4:1]+=100;
// 第3,2,1列的每个元素加100
t1;
#0 #1 #2 #3 #4
1 221 211 201 41
2 222 212 202 42
3 223 213 203 43
... ... ... ... ...

使用 m[index,] = X 修改某行,X 是一个标量或者向量。

t1=1..50$10:5;
// 赋值100到第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
... ... ... ... ...
t1[1,]+=100;
// 给第1行加100
t1;
#0 #1 #2 #3 #4
1 11 21 31 41
200 200 200 200 200
3 13 23 33 43
... ... ... ... ...

使用 m[start:end,] = X 修改多行,X 是一个标量或者向量。

t1=1..50$10:5;

t1[1:4,]=101..115;
// 将序列101..115赋值给第1,2,3行
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
... ... ... ... ...
t1[4:1, ]=101..115;
// 将序列101..115赋值给第3,2,1行
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
... ... ... ... ...

使用 m[r1:r2, c1:c2] = X 来修改矩阵窗口,X 是一个标量或者向量。

t1=1..50$5:10;
t1[1:3,5:10]=101..110;
// 将序列101..110赋值给矩阵的第1,2行和第5~9列的窗口
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;
t1[5:10, 3:1]=101..110;
// 将序列101..110赋值给矩阵的第5~9行和第2~1列的窗口
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
t1[10:5, 1:3]+=10;
// 给矩阵的第9~5行,第1~2列加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

使用m[rowIndex,colIndex] = X 来修改多个单元格,其中 rowIndex 和 colIndex 可以是标量或者向量,X 是一个标量或者向量。

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

按列对矩阵进行过滤

可以使用 lambda 表达式对矩阵的每一个列进行过滤。注意,按列对矩阵进行过滤时,lambda 表达式只能接受一个参数,并且返回的结果必须是 BOOL 类型的标量。

m=matrix(0 2 3 4,0 0 0 0,4 7 8 2);
m[x->!all(x==0)];
//返回矩阵中不全为0的列
#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];
//返回矩阵中均值大于4的列
#0 #1
5 4
3 7
6 8
9 2

对矩阵进行操作

矩阵和标量的操作:

m=1..10$5:2;
m;
#0 #1
1 6
2 7
3 8
4 9
5 10
2.1*m;
// 给矩阵中的每个元素乘2.1
#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;
// 结果是一个NULL INT的矩阵。
#0 #1

矩阵与向量的操作:

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

矩阵之间的操作:

m1=1..10$2:5
m2=11..20$2:5;

m1+m2;
// 元素逐个相加
#0 #1 #2 #3 #4
12 16 20 24 28
14 18 22 26 30
m1-m2;
// 元素逐个相减
#0 #1 #2 #3 #4
-10 -10 -10 -10 -10
-10 -10 -10 -10 -10
m1*m2;
// 元素逐个相乘
#0 #1 #2 #3 #4
11 39 75 119 171
24 56 96 144 200
// 转换矩阵m2
m2 = transpose(m2);
// 矩阵相乘
m1**m2;
#0 #1
415 440
490 520

用函数处理矩阵

矩阵是一个特殊的向量,所以大部分向量的函数都适用于矩阵。

m=1..6$2:3;
m;
#0 #1 #2
1 3 5
2 4 6
// 每列的平均值
avg(m);

[1.5,3.5,5.5]


// 每列的总和
sum(m);

[3,7,11]

// 每个元素的余弦值
cos m;
#0 #1 #2
0.540302 -0.989992 0.283662
-0.416147 -0.653644 0.96017

亦可用高阶函数 each 来计算每一个列的平均值。

与矩阵相关的函数

矩阵专用函数有:

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
// solving m*x=[1,2]
m.solve(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