NumPy是一个在Python中做科学计算的核心库,它提供了一个高性能的多维数组对象,以及用于处理这些数组的工具。
一、NumPy数据结构:数组(Arrays)
1、创建数组
NumPy数组是一个值网格,所有类型都相同,并由非负整数元组索引。数组的形状是一个整数元组,给出了每个维度的数组大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import numpy as np
a1 = np.array([1, 2, 3]) a2 = np.array([[1,2,3],[4,5,6]]) print(a1.shape)
c = np.zeros((2,2))
d = np.ones((1,2))
e1 = np.full((2,2), 7) e2 = np.full((3, 3), True, dtype=bool)
f = np.eye(2)
g = np.random.random((2,2))
b1 = np.arange(20) b2 = np.arange(2, 10) b3 = np.arange(2, 3, 0.1) b4 = np.linspace(1,4,6)
|
2、数组索引
NumPy提供了几种索引数组的方法。
(1)整数枚举索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(a[1, 2])
print(a[[0,1,2], [0,0,0]])
print(a[[0,1,2], [0,1,0]])
|
整数枚举索引的一个有用技巧是从矩阵的每一行中选择或改变一个元素。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = np.array([0, 2, 1])
print(a[np.arange(3), b])
a[np.arange(3), b] += 10 print(a)
|
(2)布尔索引
通常,这种类型的索引用于选择满足某些条件的数组元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
bool_idx = (a > 2) print(bool_idx)
print(a[bool_idx])
print(a[a > 2])
|
(3)切片索引
我们可以对NumPy数组进行切片。由于数组可能是多维的,因此必须为数组的每个维指定一个切片。
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = a[:2, 1:3] print(b)
|
还可以将整数索引与切片索引混合使用。 但是,这样做会产生比原始数组更低级别的数组。
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b1 = a[1, :] print(b1)
b2 = a[1:2, :] print(b2)
|
3、数组 I/O
NumPy 可以读写磁盘上的文本数据或二进制数据。
(1)numpy.save()+numpy.load()
NumPy 为 ndarray 对象引入了一个简单的文件格式:npy。npy 文件用于存储重建 ndarray 所需的数据、图形、dtype 和其他信息。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import numpy as np a = np.array([1,2,3,4,5])
np.save('outfile.npy',a)
np.save('outfile',a)
b = np.load('outfile.npy') print(b)
|
(2)numpy.savze()+numpy.load()
numpy.savez() 函数将多个数组保存到以 npz 为扩展名的文件中。
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np a = np.array([[1,2,3],[4,5,6]]) b = np.arange(0, 1.0, 0.1) c = np.sin(b)
np.savez("outfile.npz", a, b, sin_array = c)
z = np.load("outfile.npz") print(z)
|
(3)numpy.savetxt()+numpy.loadtxt()
savetxt() 函数是以简单的文本文件格式存储数据,对应的使用 loadtxt() 函数来获取数据。
1 2 3 4 5 6 7 8 9 10
| import numpy as np a = np.arange(0,10,0.5).reshape(4,-1)
np.savetxt("outfile.txt", a, delimiter=",")
b = np.loadtxt("outfile.txt", delimiter=",") print(b)
|
二、数组(Arrays)的基本操作
1、添加删除元素
(1)在末尾添加元素
append 函数在数组的末尾添加值。如果未提供轴,则输入数组会被展开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import numpy as np a = np.array([[1,2,3],[4,5,6]]) print(np.append(a, [7,8,9]))
print(np.append(a, [[5,5,5],[7,8,9]], axis = 1))
print(np.append(a, [[7,8,9]], axis = 0))
|
(2)在指定位置插入元素
insert 函数在给定索引之前,沿给定轴在输入数组中插入值。如果未提供轴,则输入数组会被展开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import numpy as np a = np.array([[1,2,3],[4,5,6]]) print(np.insert(a, 2, [7,8,9]))
print(np.insert(a, 1, [11], axis = 1))
print(np.insert(a, 1, [11], axis = 0))
|
(3)删除特定元素
delete 函数用于返回从输入数组中删除指定索引的新数组。如果未提供轴参数,则输入数组将展开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import numpy as np a = np.array([[1,2,3],[4,5,6]]) print(np.delete(a, 5))
print(np.delete(a, 1, axis = 0))
print(np.delete(a, 1, axis = 1))
|
(4)删除重复元素
unique 函数用于去除数组中的重复元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import numpy as np a = np.array([5,2,6,2,7,5,6,8,2,9])
print(np.unique(a))
u, indices = np.unique(a, return_index = True) print(u, indices)
u, indices = np.unique(a,return_inverse = True) print(u, indices)
u, indices = np.unique(a, return_counts = True) print(u, indices)
|
2、变换
(1)修改形状
reshape 函数有返回值,可以在不改变原数据的条件下修改形状。
resize 函数无返回值,会改变原数组的形状。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import numpy as np
a = np.arange(8) print(a)
b = a.reshape(4,2) print(b)
b.resize(2,4) print(b)
|
(2)压平
ravel(散开,解开),flatten(变平),两者所要实现的功能是一致的(将多维数组降位一维)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import numpy as np
a = np.arange(8).reshape(2,4) print(a)
print(a.flatten())
print(a.flatten(order = 'F'))
print(a.ravel())
print(a.ravel(order = 'F'))
|
区别在于返回拷贝(copy)还是返回视图(view),flatten()返回的是一份拷贝,对拷贝所做的修改不会影响原始矩阵,而ravel()返回的是视图,会影响原始矩阵。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import numpy as np
a = np.arange(8).reshape(2,4)
a.flatten()[1] = 10 print(a)
a.ravel()[1] = 10 print(a)
|
(3)转置
在处理一、二维数组时,ndarray.T 和 transpose()都可以实现矩阵转置效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import numpy as np
a = np.arange(12).reshape(3,4)
print(a)
print(np.transpose(a))
print(a.T)
|
对于高维数组,需要用到 transpose() 和一个由轴编号组成的元组,才能进行转置。
1 2 3 4 5 6 7
| import numpy as np
a = np.arange(12).reshape(2,2,3) print(a.shape)
print(a.transpose((1,0,2)))
|
(4)轴对换
swapaxes() 它接受一对轴编号,进行轴对换。
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np
a = np.arange(12).reshape(2,2,3) print(a.shape)
print(a.swapaxes(1,0)) print(a.swapaxes(0,1))
print(a.swapaxes(0,2)) print(a.swapaxes(2,0))
|
2、修改数组维度
(1)增加维度
1 2 3 4 5 6 7 8 9 10 11 12 13
| import numpy as np
a = np.arange(9).reshape(3,3)
print(a.shape)
b1 = np.expand_dims(a, axis = 0) print(b1.shape)
b2 = np.expand_dims(a, axis = 1) print(b2.shape)
|
(2)删除一维条目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import numpy as np
a = np.arange(9).reshape(1,3,3) print(a.shape)
print(a)
b = np.squeeze(a) print(b.shape)
print(b)
|
3、数组合并与拆分
(1)hstack()、vstack()、concatenate()
hstack()用于横向堆叠序列中的数组,vstack()用于纵向堆叠序列中的数组。concatenate()支持按照指定轴堆叠数组序列,可实现前两者的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import numpy as np
a = np.array([[1, 2], [3, 4]]) b = np.array([[5, 6], [7, 8]])
h1 = np.hstack((a, b)) h2 = np.concatenate((a,b), axis = 1) print(h1) print(h2)
v1 = np.vstack((a, b.T)) v2 = np.concatenate((a,b), axis = 0) print(v1) print(v2)
|
(2)hsplit()、vsplit()、split()
hsplit()指定需要分裂的array数量对原array进行水平分裂,vsplit()需要分裂的array数量对原array进行垂直分裂。split()支持按照指定轴分裂数组序列,可实现前两者的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import numpy as np
a = np.arange(16).reshape(4,4) print(a)
print(np.hsplit(a, 2)) print(np.split(a, 2, axis = 1))
print(np.vsplit(a, 2)) print(np.split(a, 2, axis = 0))
|
3、排序
(1)numpy.sort()
numpy.sort() 函数返回输入数组的排序副本。
1 2 3 4 5 6 7 8
| import numpy as np
a = np.array([[6,2], [1,4]])
print(np.sort(a, axis=0, kind='quicksort'))
|
(2)numpy.argsort()
numpy.argsort() 函数返回的是数组值从小到大的索引值。
1 2 3 4 5 6
| import numpy as np
a = np.array([5, 1, 7]) idx = np.argsort(a) print(idx) print(a[idx])
|
(3)numpy.lexsort()
numpy.lexsort() 用于对多个序列进行排序。把它想象成对电子表格进行排序,每一列代表一个序列,排序时优先照顾靠后的列。
这里举一个应用场景:小升初考试,重点班录取学生按照总成绩录取。在总成绩相同时,数学成绩高的优先录取,在总成绩和数学成绩都相同时,按照英语成绩录取…… 这里,总成绩排在电子表格的最后一列,数学成绩在倒数第二列,英语成绩在倒数第三列。
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np
a = np.array([1, 5, 7]) b = np.array([2, 1, 5]) ind = np.lexsort((a,b)) ind2 = np.lexsort((b,a))
print(ind) print([str(a[i])+","+str(b[i]) for i in ind])
print(ind2) print([str(a[i])+","+str(b[i]) for i in ind2])
|
4、搜索
(1)argmax() 、argmin()
argmax() 和 argmin()分别沿给定轴返回最大和最小元素的索引。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import numpy as np a = np.array([[30,40,70], [80,20,10], [50,90,60]])
print(np.argmax(a)) print(np.argmax(a.flatten()))
print(np.argmin(a)) print(np.argmin(a.flatten()))
print(np.argmax(a, axis = 1)) print(np.argmin(a, axis = 1))
print(np.argmax(a, axis = 0)) print(np.argmin(a, axis = 0))
|
(2)nonzero()
nonzero() 返回数组非零元素的索引。
1 2 3 4 5 6 7 8 9 10
| import numpy as np a = np.array([[0,40,70], [80,0,10], [50,90,0]])
idx = np.nonzero(a)
print(idx) print(a[idx])
|
where() 函数返回输入数组中满足给定条件的元素的索引。
extract() 函数是直接返回满足条件的元素。
1 2 3 4 5 6 7 8 9 10 11
| import numpy as np a = np.array([[0,40,70], [80,0,10], [50,90,0]])
idx = np.where(a > 30) print(a[idx])
condition = a > 30 print(np.extract(condition, a))
|
三、数组(Arrays)的算术运算
1、加减乘除
简单的加减乘除: add(),subtract(),multiply() 和 divide()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import numpy as np a = np.arange(9).reshape(3,3) b = np.array([10,10,10])
print(np.add(a,b))
print(np.subtract(a,b))
print(np.multiply(a,b))
print(np.divide(a,b))
|
2、倒数、幂和余数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import numpy as np
a = np.array([0.25, 1.33, 1, 100])
print(np.reciprocal(a))
b = np.array([1,2,3,2]) print(np.power(a, 2)) print(np.power(a, b))
print(np.mod(a, b))
|
3、三角函数
1 2 3 4 5 6 7 8 9 10
| import numpy as np a = np.array([0,30,45,60,90])
print(np.sin(a*np.pi/180))
print(np.cos(a*np.pi/180))
print(np.tan(a*np.pi/180))
|
4、指数和对数
1 2 3 4 5 6 7 8 9 10 11 12 13
| import numpy as np
a = np.array([1,30,45,60,90])
print(np.exp(a))
print(np.expm1(a))
print(np.log(a))
print(np.log10(a))
|
5、求和、求乘积
1 2 3 4 5 6 7 8
| import numpy as np
a = np.array([1,30,45,60,90])
print(np.prod(a))
print(np.sum(a))
|
6、位运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import numpy as np
print(np.binary_repr(12, width = 8)) print(bin(12))
print(np.bitwise_and(12, 6))
print(np.bitwise_or(12, 6))
print(np.invert(np.array(12, dtype = np.uint8)))
|
四、数组(Arrays)的统计运算
1、最小值、最大值
amin() 用于计算数组中的元素沿指定轴的最小值。
amax() 用于计算数组中的元素沿指定轴的最大值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import numpy as np a = np.array([[3,7,5], [8,4,3], [2,4,9]])
print(np.amin(a, 1))
print(np.amin(a, 0))
print(np.amax(a, 1))
print(np.amax(a, 0))
|
2、中位数、分位数、平均数、加权平均值
median() 函数用于计算数组中元素的中位数(中值)
percentile() 函数用于计算数组中元素的百分位数
mean() 函数返回数组中元素的算术平均值。 如果提供了轴,则沿其计算。
average() 函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值。该函数可以接受一个轴参数。 如果没有指定轴,则数组会被展开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import numpy as np
a = np.array([[30,65,70], [80,95,10], [50,90,60]])
print(np.median(a)) print(np.median(a, axis = 0))
print(np.percentile(a, 50)) print(np.percentile(a, 50, axis=0))
print(np.mean(a)) print(np.mean(a, axis = 0))
b = np.array([1,2,3,4]) wts = np.array([4,3,2,1]) print(np.average(b)) print(np.average(b, weights = wts))
|
3、标准差、方差
1 2 3 4
| import numpy as np print(np.std([1,2,3,4])) print(np.var([1,2,3,4]))
|
五、线性代数
NumPy 提供了线性代数函数库 linalg,该库包含了线性代数所需的所有功能。
1、范数
范数是对向量(或者矩阵)的度量,是一个标量(scalar)
1 2 3 4 5 6 7 8 9 10
| import numpy as np a = np.array([3, 4])
print(np.linalg.norm(a)) print(np.linalg.norm(a, ord=2))
print(np.linalg.norm(a, ord=1))
|
2、内积和外积
1 2 3 4 5 6 7 8 9 10
| import numpy as np
a = np.array([[0.0, -1.0], [1.0, 0.0]]) print(np.dot(a, a))
b = np.arange(1,6) print(np.multiply.outer(b, b))
|
3、逆矩阵
1 2 3 4 5 6 7 8
| import numpy as np
a = np.mat("0 1 2;1 0 3;4 -3 8") ia = np.linalg.inv(a) print(ia)
print(a * ia)
|
4、广义逆矩阵
inv函数只接受方阵作为输入矩阵,而pinv函数则没有这个限制
1 2 3 4 5
| import numpy as np
a = np.mat("4 11 14;8 7 -2") ia = np.linalg.pinv(a) print(ia)
|
5、奇异值分解
SVD(Singular Value Decomposition,奇异值分解)是一种因子分解运算,将一个矩阵分解为3个矩阵的乘积。numpy.linalg模块中的svd函数可以对矩阵进行奇异值分解。该函数返回3个矩阵——U、Sigma和V,其中U和V是正交矩阵,Sigma包含输入矩阵的奇异值。
原矩阵 = U(左奇异矩阵) * sigma(奇异值)* VT(右奇异矩阵的转置)
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np
a = np.mat("4 11 14;8 7 -2")
U, Sigma, Vt = np.linalg.svd(a, full_matrices=False) print ("U:", U) print ("Sigma:",Sigma) print ("Vt", Vt)
print(U * np.diag(Sigma) * Vt)
|
6、特征值分解
eigvals函数可以计算非奇异矩阵(即方阵且行列式的值不为零)的特征值,而eig函数可以返回一个包含特征值和对应的特征向量的元组
特征值和奇异值的关系
矩阵的特征值分解是一种适用于非奇异矩阵(即方阵且行列式的值不为零)的分解方法。
矩阵的奇异值分解是一种适用于任意矩阵的分解方法。对于非奇异矩阵进行奇异值分解,得到的奇异值,其实就是特征值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import numpy as np
a = np.array([[1, 2, 3], [-1,-3, 1]])
A = np.dot(a, a.T)
sigma = np.sqrt(np.linalg.eigvals(A)) print(sigma)
lamda, vector = np.linalg.eig(A) sigma2 = np.sqrt(lamda) print(sigma2)
U, sigma, Vt = np.linalg.svd(A) print(sigma)
|
7、求解线性方程组
numpy.linalg中的函数solve可以求解形如 Ax = b 的线性方程组,其中 A 为矩阵,b 为一维或二维的数组,x 是未知变量
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np
A = np.mat("1 -2 1;0 2 -8;-4 5 9") a = np.array([0, 8, -9])
x = np.linalg.solve(A, a) print(x)
print(np.dot(A , x))
|
numpy中文文档