矩阵

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

语句X $ m:n或者函数 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列和第1列。

#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);                // 要追加的向量长度必须能被矩阵的行数除尽。

1.30.16/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 = transpose(m2);       // 转换矩阵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 来计算每一个列的平均值。

与矩阵相关的函数

矩阵专用函数有 transpose, inverse(inv), det, diagsolve 等。

$ 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