在gonum/mat中还有许多有用的矩阵处理相关的函数,下面是一些例子:

初始化一个全0的矩阵

matrix1 := mat.NewDense(6, 9, nil)
fmt.Printf("%v\n", mat.Formatted(matrix1))
	
// NewDense(r, c int, data []float64) *Dense 参数说明:
// NewDense creates a new Dense matrix with r rows and c columns. If data == nil,
// a new slice is allocated for the backing slice. If len(data) == r*c, data is
// used as the backing slice, and changes to the elements of the returned Dense
// will be reflected in data. If neither of these is true, NewDense will panic.
// NewDense will panic if either r or c is zero.
// The data must be arranged in row-major order, i.e. the (i*c + j)-th
// element in the data slice is the {i, j}-th element in the matrix.

输出结果:

⎡0  0  0  0  0  0  0  0  0⎤
⎢0  0  0  0  0  0  0  0  0⎥
⎢0  0  0  0  0  0  0  0  0⎥
⎢0  0  0  0  0  0  0  0  0⎥
⎢0  0  0  0  0  0  0  0  0⎥
⎣0  0  0  0  0  0  0  0  0⎦

生成随机矩阵

data := make([]float64, 24)
	for i := range data {
		data[i] = rand.NormFloat64()
	}

	a := mat.NewDense(6, 4, data)
	fmt.Printf("%v\n", mat.Formatted(a))

输出:

⎡  -1.233758177597947  -0.12634751070237293   -0.5209945711531503      2.28571911769958⎤
⎢  0.3228052526115799    0.5900672875996937   0.15880774017643562    0.9892020842955818⎥
⎢  -0.731283016177479    0.6863807850359727     1.585403962280623    0.8382059044208106⎥
⎢  1.2988408475174342    0.5273583930598617    0.7324419258045132   -1.0731798210887524⎥
⎢  0.7001209024399848    0.4315307186960532    0.9996261210112625   -1.5239676725278932⎥
⎣-0.31653724289408824    1.8894642062634817    1.1007291937500208   -0.9927431907514367⎦

单独设置行或列的数据

我们用mat.Dense类型的成员函数SetRow、SetCol、Set来单独设置数据。

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})
	fmt.Printf("%v\n\n", mat.Formatted(a))

	a.SetRow(1, []float64{7, 8, 9})
	fmt.Printf("%v\n\n", mat.Formatted(a))

	a.SetCol(2, []float64{10, 15})
	fmt.Printf("%v\n\n", mat.Formatted(a))

	a.Set(1, 2, float64(50))
	fmt.Printf("%v\n\n", mat.Formatted(a))

输出:

⎡1  2  3⎤
⎣4  5  6⎦

⎡1  2  3⎤
⎣7  8  9⎦

⎡ 1   2  10⎤
⎣ 7   8  15⎦

⎡ 1   2  10⎤
⎣ 7   8  50⎦

克隆与复制矩阵

克隆

矩阵的克隆是指获得一个与源矩阵完全相同的新矩阵,可以使用mat.Dense类型的成员函数CloneFrom来实现。

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})
	fmt.Printf("%v\n\n", mat.Formatted(a))

	b := mat.NewDense(3, 2, []float64{
		8, 8,
		8, 8,
		6, 6})
	fmt.Printf("%v\n\n", mat.Formatted(b))

	b.CloneFrom(a)

	fmt.Printf("%v\n\n", mat.Formatted(a))
	fmt.Printf("%v\n\n", mat.Formatted(b))

输出结果

⎡1  2  3⎤
⎣4  5  6⎦

⎡8  8⎤
⎢8  8⎥
⎣6  6⎦

⎡1  2  3⎤
⎣4  5  6⎦

⎡1  2  3⎤
⎣4  5  6⎦

可以看出,不管矩阵b的形态,克隆完的新矩阵将同源矩阵(矩阵a)的形态和数据一模一样。

复制

而将一个矩阵中的数据复制到另一个矩阵可以用mat.Dense的成员函数Copy来实现。

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})
	fmt.Printf("%v\n\n", mat.Formatted(a))

	b := mat.NewDense(3, 2, []float64{
		8, 8,
		8, 8,
		6, 6})
	fmt.Printf("%v\n\n", mat.Formatted(b))

	b.Copy(a)

	fmt.Printf("%v\n\n", mat.Formatted(a))
	fmt.Printf("%v\n\n", mat.Formatted(b))

输出

⎡1  2  3⎤
⎣4  5  6⎦

⎡8  8⎤
⎢8  8⎥
⎣6  6⎦

⎡1  2  3⎤
⎣4  5  6⎦

⎡1  2⎤
⎢4  5⎥
⎣6  6⎦

可以看出,复制矩阵数据的方式是逐行逐列进行数据复制,当两个矩阵的行数和列数不同时,超出的部分将被丢弃,缺少的部分将不动。由于矩阵a比b多一列,所以a中第3列的数据都被丢弃了;而矩阵b比a多出来的第3行的数据则都没有动。

改变矩阵形态:扩张与切片

如果要扩张矩阵,可以使用mat.Dense类型的Grow成员函数,类似下面的代码:

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})
	b := a.Grow(2, 2)

	fmt.Printf("%v\n\n", mat.Formatted(b))

将得到如下所示的扩展了2行和2列的新矩阵:

⎡1  2  3  0  0⎤
⎢4  5  6  0  0⎥
⎢0  0  0  0  0⎥
⎣0  0  0  0  0⎦

反过来如果要裁剪某个矩阵则要对该矩阵做切片,此时应使用mat.Dense类型的Slice成员函数。例如要将一个2×3的矩阵右侧的2×2的子矩阵切分出来,可以用下面的代码:

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})
	b := a.Slice(0, 2, 1, 3)
	fmt.Printf("%v\n\n", mat.Formatted(b))

// Slice 参数说明
// (m *Dense) Slice(i, k, j, l int) Matrix
// Slice returns a new Matrix that shares backing data with the receiver.
// The returned matrix starts at {i,j} of the receiver and extends k-i rows
// and l-j columns. The final row in the resulting matrix is k-1 and the
// final column is l-1.
// Slice panics with ErrIndexOutOfRange if the slice is outside the capacity
// of the receiver.

Slice成员函数,它的4个参数中的第1个和第3个分别对应要截取的行数的起始索引和列数的起始索引,而第2个和第4个参数则是要截取的行数的结尾索引再加上1的值和列数的结尾索引再加上1的值。因此,我们传递的4个参数值就表示从矩阵a中的第1行第2列开始,截取到第2行第3列,注意结尾的索引都应加1,这点容易忘记。
本段代码运行后切片出来的矩阵是:

⎡2  3⎤
⎣5  6⎦

矩阵的合并

横向合并

矩阵的横向合并使用mat.Dense类型的Augment成员函数,两个矩阵只有在行数相同时才能进行横向合并。

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})

	b := mat.NewDense(2, 2, []float64{
		8, 8,
		8, 8})

	var c mat.Dense
	c.Augment(a, b)

	fmt.Printf("%v\n\n", mat.Formatted(&c))

输出结果

⎡1  2  3  8  8⎤
⎣4  5  6  8  8⎦

纵向合并

相应地,矩阵的纵向合并是使用mat.Dense类型的Stack成员函数,两个矩阵只有在列数相同时才能进行纵向合并。

a := mat.NewDense(2, 3, []float64{
		1, 2, 3,
		4, 5, 6})

	b := mat.NewDense(3, 3, []float64{
		8, 8, 8,
		8, 8, 8,
		8, 8, 8})

	var c mat.Dense
	c.Stack(a, b)

	fmt.Printf("%v\n\n", mat.Formatted(&c))

输出结果

⎡1  2  3⎤
⎢4  5  6⎥
⎢8  8  8⎥
⎢8  8  8⎥
⎣8  8  8⎦
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go