Numpy函数库中存在两种不同的数据类型(矩阵matrix和数组array),数组中的元素可以是字符等,矩阵中的只能是数,这是二者最直观的区别。
1 mat( )函数和array( )函数的区别
mat()函数将目标数据的类型转化成矩阵(matrix)。二者都可以用于处理行列表示的数字元素,虽然他们看起来很相似,但是在这两个数据类型上执行相同的数学运算可能得到不同的结果。
(1)mat( ) 函数与array( )函数生成矩阵所需的数据格式有区别,mat()函数中数据可以为字符串以分号(;)分割或者为列表形式以逗号(,)分割,而array()函数中数据只能为后者形式。
import numpy as np a = np.mat('1 3 ; 5 7') b = np.mat([[1, 2], [3, 4]]) c = np.array([[1, 3], [4, 5]]) print(a) print(type(a)) print(b) print(c) print(type(c)) # [[1 3] # [5 7]] # <class 'numpy.matrix'> # [[1 2] # [3 4]] # [[1 3] # [4 5]] # <class 'numpy.ndarray'>
(2)两者的类型不同,用mat函数转换为矩阵后才能进行一些线性代数的操作。
arr1 = np.random.rand(4, 4) mat1 = np.mat(arr1) print(arr1.I) # 'numpy.ndarray' object has no attribute 'I' print(mat1.I)
2 矩阵创建
(1)通过mat( )函数将字符串、列表、数组、随机数转换为矩阵
(2)通过eye( )函数和diag( )函数生成特殊矩阵
a1 = [1, 2, 3] a2 = np.mat(np.diag(a1)) # 生成一个对角线为1,2,3的对角矩阵 print(a2) # [[1 0 0] # [0 2 0] # [0 0 3]] a3 = np.mat(np.eye(2, 2, dtype=int)) # 产生一个2*2的对角矩阵 print(a3) # [[1 0] # [0 1]]
3 常见的矩阵运算
(1)矩阵乘(*):要求左边矩阵的列和右边矩阵的行数要一致
a1 = np.mat([1, 2]) print(a1.shape) # (1, 2) a2 = np.mat([[1], [2]]) print(a2.shape) # (2, 1) a3 = a1 * a2 print(a3) # [[5]]
(2)矩阵点乘(multiply):要求矩阵必须维数相等,即M*N维矩阵乘以M*N维矩阵,当矩阵点乘常数时,会先通过广播机制将常数扩展为与矩阵维度相等的矩阵再进行操作。
a1 = np.mat([3, 5]) print(a1.shape) # (1, 2) a2 = np.mat([4, 8]) print(a2.shape) # (1, 2) a3 = np.multiply(a1, a2) print(a3) # [[12 40]] a4 = 9 print(np.multiply(a1, a4)) # [[27 45]] 此处用到了广播机制
(3)矩阵求逆(.I):每个元素取倒数
a1 = np.mat(np.eye(2, 2)*0.5) print(a1) # [[0.5 0. ] # [0. 0.5]] a2 = a1.I print(a2) # [[2. 0.] # [0. 2.]]
(4)矩阵转置(.T):变换维度
a1 = np.mat([[1, 2, 3], [4, 5, 6]]) print(a1.shape) # (2, 3) a2 = a1.T print(a2.shape) # (3, 2)
(5)求和:sum
a1 = np.mat([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print('===== 原矩阵 =====') print(a1) a2 = np.sum(a1, axis=0) # 按列求和 a3 = np.sum(a1, axis=1) # 按行求和 a4 = np.sum(a1) # 矩阵所有元素和 a5 = np.sum(a1[1:]) # 指定行求和(所有列元素相加) a6 = np.sum(a1[:1]) # 指定列求和(所有行元素相加) print('===== 按列求和 =====') print(a2) print('===== 按行求和 =====') print(a3) print('===== 矩阵所有元素和 =====') print(a4) print('===== 指定行求和 =====') print(a5) print('===== 指定列求和 =====') print(a6)
# ===== 原矩阵 ===== # [[1 2 3] # [4 5 6] # [7 8 9]] # ===== 按列求和 ===== # [[12 15 18]] # ===== 按行求和 ===== # [[ 6] # [15] # [24]] # ===== 矩阵所有元素和 ===== # 45 # ===== 指定行求和 ===== # 39 # ===== 指定列求和 ===== # 6
(6)求最大值、最小值及对应索引(元素位置):max、min、argmax、argmin
a1 = np.mat([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) a2 = np.max(a1, axis=0) idx_max = np.argmax(a1, axis=0) a3 = np.min(a1, axis=1) idx_min = np.argmin(a1, axis=0) print('===== 所有列的最大值 =====') print(a2) print('===== 所有列的最大值对用索引 =====') print(idx_max) print('===== 所有列的最小值 =====') print(a3) print('===== 所有列的最小值对用索引 =====') print(idx_min) # ===== 所有列的最大值 ===== # [[7 8 9]] # ===== 所有列的最大值对用索引 ===== # [[2 2 2]] # ===== 所有列的最小值 ===== # [[1] # [4] # [7]] # ===== 所有列的最小值对用索引 ===== # [[0 0 0]]
4 矩阵分割与合并
矩阵的分割,同列表和数组的分割一致;矩阵合并要求被操作的矩阵形状相同(所有维度数量必须一致)。
a = np.mat(np.ones((2, 2))) print(a.shape) # (2, 2) b = np.mat(np.eye(2)) print(b.shape) # (2, 2) c = np.vstack((a, b)) # 按照列和并,即增加行数 print(c.shape) # (4, 2) d = np.hstack((a, b)) # 按照行合并,即行数不变,扩展列数 print(d.shape) # (2, 4)
5 矩阵、数组、列表转换
5.1 三者的区别
(1)列表中元素可以是不同类型的数据;
(2)数组中的元素必须为同一个类型;
(3)矩阵中的元素必须为数值型,同时具有数组属性(shape、ndim、size、dtype)
5.2 具体转换
(1)列表转换
a1 = [1, 2, 3] print(a1, type(a1)) # [1, 2, 3] <class 'list'> a2 = np.array(a1) print(a2, type(a2)) # [1 2 3] <class 'numpy.ndarray'> a3 = np.mat(a1) print(a3, type(a3)) # [[1 2 3]] <class 'numpy.matrix'>
(2)数组转换
a4 = a2.tolist() print(a4, type(a4)) # [1, 2, 3] <class 'list'> a5 = np.mat(a2) print(a5, type(a5)) # [[1 2 3]] <class 'numpy.matrix'>
(3)矩阵转换
a6 = a3.tolist() print(a6, type(a6)) # [[1, 2, 3]] <class 'list'> 与a1有区别 a7 = np.array(a3) print(a7, type(a7)) # [[1 2 3]] <class 'numpy.ndarray'> 与a2有区别
注意:当列表是一维的时候,将它转换成数组和矩阵后,再通过tolist()转换成列表是不相同的。