目录
NumPy 入门
使用 NumPy 库需先导入 numpy 模块,习惯性,我们将导入后的模块重新命名为 np。
import numpy as np
下面,我们主要学习 numpy 中的两种数据结构
数组(Ndarray)
创建数组对象
有以下多种常用的创建数组对象的方法:
- 用 np.array() 函数将 python 列表数组(list)转换为 numpy 的数组对象。
>>> np.array([1,2,3,4])
array([1, 2, 3, 4])
- np.arange() 函数,传入一到三个参数。arange([start,] stop, [step] ),其中start默认为0,step默认为1。此外,和 list(range()) 生成数组一样,np.arange() 生成的数组不包含 stop。
>>> np.arange(3)
array([0, 1, 2])
>>> np.arange(3.0)
array([ 0., 1., 2.])
>>> np.arange(3,7)
array([3, 4, 5, 6])
>>> np.arange(3,7,2)
array([3, 5])
- np.ones() 函数和 np.zeros() 函数 生成全1或全0数组。np.empty() 函数生成空数组(实际上是未初始化数组,其内部每个元素是有具体值的)。ones/zeros/empty(shape, dtype=None) shape参数要求传入为整数或只含整数的序列(元组、列表)。
>>> np.ones(5)
array([1., 1., 1., 1., 1.])
>>> np.ones((5,), dtype=int)
array([1, 1, 1, 1, 1])
>>> np.zeros((2, 1))
array([[ 0.],
[ 0.]])
>>> s = (2,2)
>>> np.zeros(s)
array([[ 0., 0.],
[ 0., 0.]])
>>> np.empty([2, 2])
array([[ -9.74499359e+001, 6.69583040e-309],
[ 2.13182611e-314, 3.06959433e-309]]) #uninitialized
>>> np.empty([2, 2], dtype=int)
array([[-1073741821, -1067949133],
[ 496041986, 19249760]]) #uninitialized
- np.random.rand() 函数创建0~1随机数数组。rand(d0, d1, …, dn) 此函数创建多维数组时,传入多个参数即可。如果需要更多生成随机数组的函数,在 shell 用 print 函数打印 np.random 的__doc__属性即可了解。
>>> np.random.rand(3,2)
array([[ 0.14022471, 0.96360618], #random
[ 0.37601032, 0.25528411], #random
[ 0.49313049, 0.94909878]]) #random
- np.random.randn() 函数创建满足 N(0,1) 分布的随机数组,使用方法同 np.random.rand()。
>>> np.random.randn(2,3)
array([[ 0.26342371, -1.24474075, 0.74389122],
[-0.11589208, 1.56492929, -1.11223659]])
- np.random.linspace() 函数可以将指定的范围均分为指定长度的数组。linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0) 将从 start 到 stop 的范围,均分为 num 个点的数组,endpoint 默认 True 表示包括 stop 点。retstep 如果设置为 True ,最后返回的会是一个元组,元组第一个参数是 array 数组,第二个参数是步长。
>>> np.linspace(2.0, 3.0, num=5)
array([2. , 2.25, 2.5 , 2.75, 3. ])
>>> np.linspace(2.0, 3.0, num=5, endpoint=False)
array([2. , 2.2, 2.4, 2.6, 2.8])
>>> np.linspace(2.0, 3.0, num=5, retstep=True)
(array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
数组的查询操作
这里我们和 python 列表(List)一样,分为“索引”和“切片”两块介绍。
以二维数组 array 和三维数组 array2 为例,我们先创建这个两个数组。(后面的内容也需要用到这两个数组)
>>> array = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
>>> array2 = np.array([[[1,2,3,4],[5,6,7,8],[9,10,11,12]],
[[9,10,11,12],[5,6,7,8],[1,2,3,4]]])
提取单独元素的索引
方法一:和列表一样的索引方式
>>> array[2]
array([ 9, 10, 11, 12])
>>> array[2][2]
11
方法二:Ndarray 独有的索引方式,在中括号中,用逗号隔开对不同维数的索引。
>>> array[2,2]
11
>>> array2[0,2]
array([ 9, 10, 11, 12])
提取子数组的索引(切片)
一维数组索引: 一维数组的切片操作和 python 的列表一样。
>>> a = np.arange(5)
>>> a[:2]
array([0, 1])
多维数组索引: 用逗号隔开不同维数的切片,其余格式和一维数组索引一样。(位于后面的维数如果不需要索引的话可以不写)
>>> array[1:3,2:4]
array([[ 7, 8],
[11, 12]])
>>> array2[:,1:]
array([[[ 5, 6, 7, 8],
[ 9, 10, 11, 12]],
[[ 5, 6, 7, 8],
[ 1, 2, 3, 4]]])
数组的修改(部分赋值)操作
我们将数组的索引、切片写在等号左侧,可对数组进行部分赋值。
>>> array[0:2,0:2] = [[0,1],[2,3]]
>>> array
array([[ 0, 1, 3, 4],
[ 2, 3, 7, 8],
[ 9, 10, 11, 12]])
>>> array[2][2] = 100
>>> array
array([[ 0, 1, 3, 4],
[ 2, 3, 7, 8],
[ 9, 10, 100, 12]])
数组的属性
shape 属性:数组的结构(返回一个整数元组,表示数组各个维度的长度)
dtype 属性:数组元素的数据类型(返回 numpy.dtype 对象,表示数据类型)
size 属性:数组含有元素个数(返回 int 对象,表述数组含有数据的个数)
itemsize 属性:数组元素数据类型所占字节数(返回 int 对象)
ndim 属性:数组维度(返回 int 对象)
>>> for s in ['shape','dtype','size','itemsize','ndim']:
print(s,':\t',str(eval('array.'+s)))
shape : (3, 4)
dtype : int32
size : 12
itemsize : 4
ndim : 2
可能被修饰为属性的方法:
T 属性:返回数组的转置
数组的方法
- reshape() 方法。改变数组的维数结构并作为返回值返回。传入若干个参数分别表示新的结构每一维的长度,改变前后各维数长度乘积应该一致(元素个数必须相等),最后一个维度长度参数可以传入 -1 。
>>> array3 = array.reshape(2,-1)
>>> array3
array([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12]])
数组相关的 numpy 库常用函数
- np.append() 函数。
append(arr, values, axis=None) 在 axis 指定为整数 i 时(范围为 0 ~ ndim-1 ),传入至少两个数组参数(可以是 ndarray 对象或 list 对象),使数组的 shape[i] 代表的维度增加若干元素,并将拓宽后的 ndarray 对象作为返回值返回。(例如2维数组,axis=1 时为拓宽列数,axis=0 时为拓宽行数;3维数组,axis=2 时为拓宽每一块的列数)
arr 参数为增加前的数组,values 为需要增加的元素组成的数组,注意 values 的维度和 arr 应一致,且 shape 属性除了第 i 元素外其他元素应相等(例如 2维数组在 axis=1 条件下,列数(ndarray.shape[1])可以不一样,但其他维数长度必须相等)。
注意:np.append() 函数,输入的两个数组参数和返回值的维度两两相等。
axis 为默认值 None 时,arr 和 values 会默认变为一维数组,此时对传入数组的结构无要求。
>>> array3 = np.append(array,[[1],[2],[3]],axis=1)
>>> array4 = np.append([[1,2],[3,4]],[[1],[2]])
>>> array5 = np.append(array2,array2,0)
>>> print(array3,array4,array5,sep='\n————————\n')
[[ 1 2 3 4 1]
[ 5 6 7 8 2]
[ 9 10 11 12 3]]
————————
[1 2 3 4 1 2]
————————
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[ 9 10 11 12]
[ 5 6 7 8]
[ 1 2 3 4]]
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[ 9 10 11 12]
[ 5 6 7 8]
[ 1 2 3 4]]]
- np.delete() 函数。
delete(arr, obj, axis=None) 在 axis 指定为整数 i 时(范围为 0 ~ ndim-1 ),使数组 arr 的 shape[i] 代表的维度删除指定的一些列(行),并将删除部分元素后的 ndarray 对象作为返回值返回。(例如2维数组,axis=1 时为删除某些列,axis=0 时为删除某些行数;3维数组,axis=2 时为拓宽每一块的列数)
arr 参数为删除前的数组,obj为需要删除的行(列)的序号(范围为 0 ~ ndim-1 ),可以是整数或整数组成的序列。
axis 为默认值 None 时,arr 会默认变为一维数组。
>>> np.delete(array, 1, 0)
array([[ 1, 2, 3, 4],
[ 9, 10, 11, 12]])
>>> np.delete(array, np.s_[::2], 1)
array([[ 2, 4],
[ 6, 8],
[10, 12]])
>>> np.delete(array, [1,3,5], None)
array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
- np.vstack() 纵向堆叠函数 和 np.hstack() 横向堆叠函数。
传入一个元组参数(其实可以是列表,但容易和列表类型的数组搞混),里面包含你需要堆叠的若干个列数(或行数)相等的一维或二维数组,返回将其纵向(或横向)堆叠拼接后的一维或二维的 ndarray 对象。
注意:和 np.append() 函数的区别在于,其传入、返回的对象的维度可以不一致,且可以将多个对象(但需要放到一个元组里)进行拼接。
>>> np.append([[1,2]],[[3,4]],0)
array([[1, 2],
[3, 4]])
>>> np.vstack(([1,2],[3,4]))
array([[1, 2],
[3, 4]])
>>> np.hstack(([1,2],[3,4],[5]))
array([1, 2, 3, 4, 5])
矩阵(Matrix)
创建矩阵对象
- np.mat() 传入一维或二维数组或列表,返回矩阵对象。(结合数组中的特殊数组创建方法,则可以创建一些特殊矩阵)
>>> np.mat(np.ones((3,3),int))
matrix([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
>>> np.mat([0])
matrix([[0]])
矩阵的查询操作
和数组完全一致。
矩阵的属性
shape 属性:返回一个元组,包含矩阵的行数、列数。
size 属性:返回一个整数,代表矩阵内元素的个数。
dtype 属性:返回 numpy.dtype 对象,代表矩阵内元素的类型。
>>> array = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
>>> matrix = np.mat(array)
>>> for x in ['shape','size','dtype']:
print(x,':',str(eval('matrix.'+x)))
shape : (3, 4)
size : 12
dtype : int32
可能被修饰为属性的方法:
T 属性:返回矩阵的转置
矩阵的方法
- tolist() 方法,可以将矩阵变为列表。
>>> matrix.tolist()
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
矩阵相关的 numpy 库常用函数
- np.delete() 删除函数。
和数组的删除操作基本一致,唯一区别是当 axis 为默认值 None 时,矩阵不会变为一维(因为矩阵就是二维的),但行数仍会被压扁到一行。
# 仍用上面的 matrix 矩阵
>>> np.delete(matrix,1,0)
matrix([[ 1, 2, 3, 4],
[ 9, 10, 11, 12]])
>>> np.delete(matrix,(1,3,5,7))
matrix([[ 1, 3, 5, 7, 9, 10, 11, 12]])
矩阵增加操作(比较奇特)
- np.c_[此处为若干个数组或矩阵] 行连接方法 和 np.r_[此处为若干个数组或矩阵] 列连接方法。(行连接相当于左右拓宽,列连接相当于上下拓宽)
注意:这个不是函数,甚至 _ 后面都不是小括号,而是用中括号。
>>> array = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
>>> matrix = np.mat(array)
>>> np.c_[matrix,array,[[1],[2],[3]]]
matrix([[ 1, 2, 3, 4, 1, 2, 3, 4, 1],
[ 5, 6, 7, 8, 5, 6, 7, 8, 2],
[ 9, 10, 11, 12, 9, 10, 11, 12, 3]])
矩阵的数学操作
- 矩阵乘法
方法一:使用 * 乘号可以直接实现矩阵乘法
方法二:对一个矩阵 mat1 使用方法 .dot() 可以使 mat1 右乘一个矩阵。
>>> mat1 = np.mat([1,2,3])
>>> mat1.T * mat1
matrix([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
>>> mat1.dot(mat1.T)
matrix([[14]])
- 矩阵求逆
使用 np.linalg.inv() 函数,传入一个矩阵,返回该矩阵的逆矩阵。如果传入的矩阵为奇异矩阵,则会抛出错误。
>>> mat2 = np.mat([[1,2],[3,4]])
>>> np.linalg.inv(mat2)
matrix([[-2. , 1. ],
[ 1.5, -0.5]])
>>> np.linalg.inv([[0,1],[0,0]])
Traceback (most recent call last):
File "<pyshell#95>", line 1, in <module>
np.linalg.inv([[0,1],[0,0]])
File "<__array_function__ internals>", line 6, in inv
File "D:\py\lib\site-packages\numpy\linalg\linalg.py", line 547, in inv
ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
File "D:\py\lib\site-packages\numpy\linalg\linalg.py", line 97, in _raise_linalgerror_singular
raise LinAlgError("Singular matrix")
numpy.linalg.LinAlgError: Singular matrix
- 矩阵求特征值
使用 np.linalg.eig() 函数,传入一个矩阵,返回一个元组,元组第一个值为该矩阵的特征值组成的 ndarray 数组,元组的第二个值为特征值对应的标准化后的特征向量按列组成的矩阵(第一列代表的特征向量对应第一个特征值)。
>>> np.linalg.eig([[1,2],[2,1]])
(array([ 3., -1.]), array([[ 0.70710678, -0.70710678],
[ 0.70710678, 0.70710678]]))
'''此处特征值 3 对应的标准化特征向量为 (0.7071,0.7071)'''
- 矩阵求行列式
使用 np.linalg.det() 函数,传入一个矩阵(或多个矩阵组成的数组),返回矩阵的行列式数值(或多个数值组成的数组。
>>> np.linalg.det([[1,2],[3,4]])
-2.0000000000000004
- 矩阵指数函数
python 自带的 exp 函数,无法对矩阵进行运算,需要使用 np.exp()。