NumPy(Numerical Python) 是 Python的一个很重要的第三方库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。很多其他科学计算的第三方库都是以Numpy为基础建立的,比如pandas的数据就是以numpy为基础。
numpy 是一个科学计算库 ,它的核心:多维数组-ndarray(数组)。ndarray 数据存储方式和list不一样,ndarray是用一块整体的内存来存储数据的。
一、首先导入包
import numpy as np
二、创建数组
通过list创建、np.array初始化
通过list创建、然后使用np.array对其进行初始化而创建数组。
a = [1,2,3,4,5,6,7,8]
arr = np.array(a)
或者
arr = np.array([[[1, 2]], [[2, 3]], [[3, 4]], [[4, 5]]])
reshape创建二维数组
通过reshape创建二维数组
x = np.arange(10).reshape((2, 5))
print(x)
print(x[1, 4])
print(x.shape[0])
# [[0 1 2 3 4]
# [5 6 7 8 9]]
# 9
# 2
二维数组的索引方式有两种,第一种是a[x][y]的方式,另一种是a[x,y],通常更推荐后者。
数组array属性
- ndim---维度,数组的维度大小,也就是几维数组
- shape---形状,各个维度的大小
- size---元素个数,数组元素总的个数
- dtype---数据类型
- itemsize---数组的每个元素的大小
- flags--数组的内存信息
- real--数组的元素的实部
- imag--数组的元素的虚部
- data--包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。
arr = np.array([[[1, 2]], [[2, 3]], [[3, 4]], [[4, 5]]])
print(type(arr))
print('arr:\n',arr)
print('数组的维度:',arr.ndim)
print('数组的形状:',arr.shape)
print('数组的元素个数:',arr.size)
print('数组的数组类型:',arr.dtype)
print('数组的每个元素的大小:',arr.itemsize)
输出结果如下:
arr:
[[[1 2]]
[[2 3]]
[[3 4]]
[[4 5]]]
数组的维度: 3
数组的形状: (4, 1, 2)
数组的元素个数: 8
数组的数组类型: int32
数组的每个元素的大小: 4
特殊数组
np.empty空数组创建
生成空数组,np.empty空数组创建
x = np.empty([3,2], dtype = int)
print (x)
通过np.empty创建3*2的int的空数组,数组元素为随机值,因为它们未初始化。
np.zeros()
生成全0数组,,通过dtype可以指定数组中元素类型
z = np.zeros(10)
print(z) # 默认是浮点数 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
z1 = np.zeros(10, dtype='int64')
print(z1) # [0 0 0 0 0 0 0 0 0 0]
np.zeros_like
创建一个与给定数组具有相同形状的数组,数组元素以 0 来填充。
numpy.zeros 可以直接指定要创建的数组的形状,而 numpy.zeros_like 则是创建一个与给定数组具有相同形状的数组。
# 创建一个 3x3 的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 创建一个与 arr 形状相同的,所有元素都为 0 的数组
zeros_arr = np.zeros_like(arr)
print(zeros_arr)
np.ones()
生成全1数组
one = np.ones(10, dtype='int64')
print(one) # [1 1 1 1 1 1 1 1 1 1]
numpy.ones_like
创建一个与给定数组具有相同形状的数组,数组元素以 1 来填充。numpy.ones 可以直接指定要创建的数组的形状,而 numpy.ones_like 则是创建一个与给定数组具有相同形状的数组。
# 创建一个 3x3 的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 创建一个与 arr 形状相同的,所有元素都为 1 的数组
ones_arr = np.ones_like(arr)
print(ones_arr)
np.arange
生成某个范围内的数组
aa = np.arange(10)
# [0 1 2 3 4 5 6 7 8 9]
bb = np.arange(0, 10, 3,dtype = float) # 指定起始点 终止点 以及 step
# [0 3 6 9]
numpy.linspace
创建一个一维数组,数组是一个等差数列构成的
a = np.linspace(1,10,10)
print(a)
#[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
a = np.linspace(10, 20, 5, endpoint = False) # endpoint 设为 false,不包含终止值20
print(a)
#[10. 12. 14. 16. 18.]
numpy.logspace
创建一个于等比数列。
# 默认底数是 10
a = np.logspace(1.0, 2.0, num = 10)
print (a)
#[ 10. 12.91549665 16.68100537 21.5443469 27.82559402
# 35.93813664 46.41588834 59.94842503 77.42636827 100. ]
np.eye()
生成单位矩阵,即生成对角为1的二维矩阵。
a = np.eye(10)
print(a)
# [[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
# [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
# [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
# [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
# [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
# [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
# [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
# [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
# [0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
# [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]]
三、数组的切片操作
array和list的切片区别
a = list(range(10))
b = np.arange(10)
a1 = a[0:4]
b1 = b[0:4]
print("a_list:{}".format(a))
print("b_array:{}".format(b))
print("a1_list:{}".format(a1))
print("b1_array:{}".format(b1))
print("修改a1[0]和b1[0]的值之后:")
a1[0] = 11
b1[0] = 11
print("修改之后的a_list:{}".format(a)) # list的值并没有被修改 它相当于是一种浅拷贝
print("修改之后的b_array:{}".format(b)) # array的值被修改
# 说明对array来说,切片操作其实是对原array的引用,实际上是一种浅拷贝
运行结果如下:
a_list:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b_array:[0 1 2 3 4 5 6 7 8 9]
a1_list:[0, 1, 2, 3]
b1_array:[0 1 2 3]
修改a1[0]和b1[0]的值之后:
修改之后的a_list:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
修改之后的b_array:[11 1 2 3 4 5 6 7 8 9]
需要注意的点
a = b,完全不复制,ab会相互影响;
a = b[:],切片操作,会创建新的对象a,但是两者的变化是一致的;
a = b.copy(),复制,两者互不影响,相当于深拷贝。
二维数组切片
a = np.arange(15).reshape((3, 5))
print(a)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]]
print(a[0:2, 0:2])
# [[0 1]
# [5 6]]
print(a[0:2][0:2])
# [[0 1 2 3 4]
# [5 6 7 8 9]]
# 只有前一种方法凑效
print(a[1:, 2:4])
# [[ 7 8]
# [12 13]]
四、数组索引
布尔索引
将布尔表达式作为索引
a = np.arange(10)
b = a[a > 5]
print(b)
# [6 7 8 9]
其实它的实际操作是这样的
c = np.array([1, 2, 3, 4])
d = [True, True, False, True]
print(c[d]) # [1, 2, 4]
print(a > 5) # [False False False False False False True True True True]
print(a[a > 5]) # [6 7 8 9]
取a中大于5的偶数
b = a[(a > 5) & (a % 2 == 0)] # 必须要加括号 并且不能用and 此处会重载运算符&
print(b)
# [6 8]
取a中大于5的数和所有偶数
c = a[(a > 5) | (a % 2 == 0)]
print(c) # [0 2 4 6 7 8 9]
花式索引
传进去一个列表作为索引,可以取到相应位置上的值
也可以和切片操作、布尔索引结合
a = np.arange(20)
print(a[[1, 3, 5, 7, 9]]) # [1 3 5 7 9]
a = np.arange(20).reshape((4, 5))
print(a)
print(a[0, 2:4]) # [2, 3]
print(a[0, a[0] > 1]) # [2, 3, 4]
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
# 取a中的元素作为新的二维数组
b = a[[1, 3], :] # 先切第1 3行
c = b[:, [1, 3]] # 再切第1 3列
print(c)
# [[ 6 8]
# [16 18]]
print(a[[1, 3], :][:, [1, 3]]) # 效果同上
print(a[[0, 2], :][:, [0, 1, 3, 4]])
五、numpy中的重要函数
np.isnan
nan(not a number)不是一个数,类型是
两个NaN是不相等的 np.nan == np.nan ==> False
np.nan != np.nan ==> True
# 判断nan的方法是np.isnan(a)
a = np.arange(5)
a = a / a
print(a) # [nan 1. 1. 1. 1.]
print(np.isnan(a)) # [True False False False False]
# 去掉数组中nan的方法
b = a[~np.isnan(a)] # [1. 1. 1. 1.]
# 统计数组中nan的个数
np.count_nonzero(a != a)
np.isinf
inf是无穷大,也是float型数据。用法同isnan
a = np.array([1, 1, 2, 3, 4])
b = np.array([0, 1, 2, 1, 0])
c = a / b
print(c) # [inf 1. 1. 3. inf]
# 去除inf
print(c[~(np.isinf(c))]) # [1. 1. 3.]
np.random
随机产生一个数
t = np.random.rand(2,4) # 产生多个维度均匀分布的数 或者 数组 范围0~1
# [[0.90817816 0.75715337 0.64737834 0.79045973]
# [0.80215137 0.04848201 0.66005689 0.32470002]]
t = np.random.randn(4) # 产生多个维度成标准正态分布的数组 均值为0 标准差为1
# [ 0.33196007 -1.59954454 -1.22863283 0.49101622]
a = np.random.random()
产生某个范围内的整数或数组
np.random.randint(0, 10)
a = np.random.randint(0, 10, 10) # 随机生成10个0-9以内的int 一维的
# [9 0 2 3 2 0 8 9 2 6]
a = np.random.randint(0, 10, (2, 5)) # 最后一参数是形状 多维
# [[4 8 7 0 3]
# [7 6 8 1 8]]
产生成均匀分布的数组
a = np.random.uniform(2.0, 10.0, 10)
print(a)
# [3.10070825 2.54493484 8.07038208 6.74178579 2.9491971 9.9813392 3.58365099 8.4720269 4.73902394 6.50748841]
a = np.random.uniform(2.0, 10.0, (2, 5))
print(a)
# [[6.86870706 8.48767828 3.35503304 2.35793278 6.05281056]
# [9.67359048 3.16650548 7.81726608 2.72933486 2.22826293]]
随机数种子
因为计算机每次生成的都是伪随机数,在指定随机数种子之后,生成的随机数就不会改变。
np.random.seed(4)
t = np.random.randint(0, 10, (2, 5))
print(t)
# [[7 5 1 8 7]
# [8 2 9 7 7]]
随机选择数组中的数形成新数组
a = np.random.choice([1, 2, 3, 4, 5], 10) # 最后一个参数是生成数组的形状
print(a) # [2 2 2 2 1 1 3 5 3 3]
np.where函数
np.where函数的使用,可以理解为:
(1)三个参数np.where(condition,x,y) : 满足条件(condition)输出x, 不满足则输出y ;
(2)一个参数np.where(arr) : 输出arr中“真”值的坐标,简单理解为不为0的坐标。
x=np.arange(1,10).reshape(3,3)
np.where(x>3,x,11111)
# [[11111 11111 11111]
# [ 4 5 6]
# [ 7 8 9]]
其它函数
print(np.maximum(a, b))
print(np.minimum(a, b))
a = np.array([1, 2, 3, 4, 5])
# 若a是二维数组,则可以指定axis用以在不同轴上取数据
t1 = np.arange(0, 20).reshape((4, 5))
print(t1.sum(axis=0)) # 枚举行
# [30 34 38 42 46]
print(t1.sum(axis=1)) # 枚举列
# [10 35 60 85]
print(a.max())
print(a.min())
print(a.mean())
print(a.sum())
print(a.argmax())
print(a.argmin())
print(a.std())
print(a.var())
四舍五入相关类
a = np.arange(-5, 5, 0.6)
print(a)
print(np.floor(a)) # 向上取整
print(np.ceil(a)) # 向下取整
print(np.rint(a)) # 四舍五入
print(np.round(a)) # 四舍五入
print(np.trunc(a)) # 截断小数部分
六、数组的拼接vstack和hstack
垂直拼接需要保证两个数组在列维度上大小相同
水平拼接需要保证两个数组在行维度上大小相同
# 垂直拼接
t1 = np.arange(0, 10).reshape((2, 5))
t2 = np.arange(11, 21).reshape((2, 5))
tv = np.vstack((t1, t2))
print(tv)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [11 12 13 14 15]
# [16 17 18 19 20]]
# 水平拼接
t1 = np.arange(0, 10).reshape((2, 5))
t2 = np.arange(11, 21).reshape((2, 5))
th = np.hstack((t1, t2))
print(th)
# [[ 0 1 2 3 4 11 12 13 14 15]
# [ 5 6 7 8 9 16 17 18 19 20]]
数组的行列交换
t1 = np.arange(0, 20).reshape((4, 5))
print(t1)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
t1[[1, 2], :] = t1[[2, 1], :] # 行交换之后
print(t1)
# [[ 0 1 2 3 4]
# [10 11 12 13 14]
# [ 5 6 7 8 9]
# [15 16 17 18 19]]
t1[:, [0, 1]] = t1[:, [1, 0]] # 列交换之后
print(t1)
# [[ 1 0 2 3 4]
# [11 10 12 13 14]
# [ 6 5 7 8 9]
# [16 15 17 18 19]]
七、NumPy 矩阵库(Matrix)
NumPy 中包含了一个矩阵库 numpy.matlib,该模块中的函数返回的是一个矩阵,而不是 ndarray 对象。
转置矩阵
NumPy 中除了可以使用 numpy.transpose 函数来对换数组的维度,还可以使用 T 属性。
# 水平拼接
a = np.arange(12).reshape(3,4)
print ('原数组:')
print (a)
# 原数组:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print ('\n')
print ('转置数组:')
print (a.T)
#转置数组:
# [[ 0 4 8]
# [ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]]
矩阵计算方法
加法、减法、乘法、除法、整除、乘方、求余、求倒数、求绝对值、求三角函数和反三角函数、以 e 为底的函数值、n 的 x 次方、求对数函数等。这个很好理解,就是对矩阵中每个元素进行计算。
import numpy as np
x = np.arange(1,16).reshape(3,5)
print(x)
# 加法(减法)
x1 = x + 1
print(x1)
# 除法(乘法)
x2 = 2 * x
print(x2)
x3 = 2 / x
print(x3)
# 向下取整
x4 = x // 3
print(x4)
# 取余
x5 = x % 3
print(x5)
#绝对值
x6 = np.abs(x)
print(x6)
#正弦
sinx = np.sin(x)
print(sinx)
#余弦
cosx = np.cos(x)
print(cosx)
#正切
tanx = np.tan(x)
print(tanx)
# 反正弦
arcsinx = np.arcsin(x)
print(arcsinx)
# 反余弦
arccosx = np.arccos(x)
print(arccosx)
# 反正切
arctanx = np.arctan(x)
print(arctanx)
#次方运算
xxx = x **3
print(xxx)
xx = 2 ** x
print(xx)
# 指数函数e**x
expx = np.exp(x)
#开平方:sqrt
sqrtx = np.sqrt(x)
print(sqrtx)
#power(a,b):求a的b次方
powerx = np.power(2,x)
#log函数:不指定值时默认就是loge函数,以e为底的对数
lnx = np.log(x)
print(lnx)
#long2:以2为底的对数
ln2x = np.log2(x)
print(ln2x)
#long10:以10为底的对数
ln10x = np.log10(x)
print(ln10x)
矩阵运算
矩阵的运算:两个矩阵加法、减法、乘法。
A = np.arange(4).reshape(2,2)
B = np.full((2,2),10)
# 矩阵间的加减法
AB = A + B
print(AB)
A_B = A - B
print(A_B)
# 矩阵的乘法
AB = A.dot(B)
print(AB)
# 两矩阵间如仅用乘号(*)相连接,计算结果为两矩阵对应元素相乘的结果
AB = A * B
print(AB)
矩阵的转置
# 矩阵的转置
AT = A.T
print(AT)
向量与矩阵的运算
加法(数学上无意义),相当于将矩阵的每一行加上向量对应的值。
[[37 加法(数学上无意义)40]
[85 92]]
乘法(与矩阵间计算相似),注:向量与矩阵相乘时,若不满足数学计算规则,numpy会自动将矩阵进行转置。
矩阵的堆叠
np.title(v, (2,2))
np.title(v, (2,1))
矩阵的逆
np.linalg.inv()
生成伪逆矩阵
np.linalg.pinv()
八、NumPy 线性代数
函数 | 描述 |
dot | 两个数组的点积,即元素对应相乘。 |
vdot | 两个向量的点积 |
inner | 两个数组的内积 |
matmul | 两个数组的矩阵积 |
determinant | 数组的行列式 |
solve | 求解线性矩阵方程 |
inv | 计算矩阵的乘法逆矩阵 |
numpy.dot()
a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
print(np.dot(a,b))
输出结果为:[[37 40] [85 92]]
计算式为:[[1*11+2*13, 1*12+2*14],[3*11+4*13, 3*12+4*14]]
numpy.vdot()
numpy.vdot() 函数是两个向量的点积。 如果第一个参数是复数,那么它的共轭复数会用于计算。 如果参数是多维数组,它会被展开。
import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
# vdot 将数组展开计算内积
print (np.vdot(a,b))
#130
计算式为:1*11 + 2*12 + 3*13 + 4*14 = 130
numpy.inner()
numpy.inner() 函数返回一维数组的向量内积。对于更高的维度,它返回最后一个轴上的和的乘积。
import numpy as np
print (np.inner(np.array([1,2,3]),np.array([0,1,0])))
# 等价于 1*0+2*1+3*0
#2
多维数组:
import numpy as np
a = np.array([[1,2], [3,4]])
b = np.array([[11, 12], [13, 14]])
print ('内积:')
print (np.inner(a,b))
# 内积:
# [[35 41]
# [81 95]]
内积计算式为:
1*11+2*12, 1*13+2*14
3*11+4*12, 3*13+4*14
numpy.linalg.det()
numpy.linalg.det() 函数计算输入矩阵的行列式。
行列式在线性代数中是非常有用的值。 它从方阵的对角元素计算。 对于 2×2 矩阵,它是左上和右下元素的乘积与其他两个的乘积的差。
换句话说,对于矩阵[[a,b],[c,d]],行列式计算为 ad-bc。 较大的方阵被认为是 2×2 矩阵的组合。
import numpy as np
a = np.array([[1,2], [3,4]])
print (np.linalg.det(a))
#-2.0
numpy.linalg.solve()
numpy.linalg.solve() 函数给出了矩阵形式的线性方程的解。
求解方程组 x0 + 2 * x1 = 1 和 3 * x0 + 5 * x1 = 2 :
a = np.array([[1, 2], [3, 5]])
b = np.array([1, 2])
x = np.linalg.solve(a, b)
# [-1., 1.]
# x0=-1 x1=1
numpy.linalg.inv()
numpy.linalg.inv() 函数计算矩阵的乘法逆矩阵。
逆矩阵(inverse matrix):设A是数域上的一个n阶矩阵,若在相同数域上存在另一个n阶矩阵B,使得: AB=BA=E ,则我们称B是A的逆矩阵,而A则被称为可逆矩阵。注:E为单位矩阵。
九、数组的保存与读取
save 以二进制形式来保存数组
保存的文件是以.npy为后缀的二进制文件,参数1: 保存的文件路径名称,可省略文件名后缀。
np.save('./arr1',arr1)
3、读取npy文件
arr = np.load('./arr1.npy')
4、通过savez来保存多个数组
默认保存的是以.npz结尾的二进制文件
np.savez('./arr2', arr1, arr2)
5、加载文件中的数组
多个数组时,是以键值对存储的。
6、文本形式的保存
参数:fmt---保存的数组数据类型,delimiter---分隔符
np.savetxt('./arr1.txt', fmt='%d',delimiter=' ')
np.savetxt('./arr1.csv', fmt='%d',delimiter=',')
7、加载文本形式的数组
data = np.loadtxt('./arr1.txt', dtype=float,delimiter=' ')
8、genfromtxt可以读取结构化数组和缺失数据
genfromtxt读取文件和loadtxt类似,所不同的是,参数filling_values 指定缺失时填充的数据。
data = np.genfromtxt('./arr1.txt',dtype=int,delimiter=' ', filling_values=9999)
十、数组的倒序
1. 升序排序,而且会对原数组产生影响
arr.sort()
2、argsort 返回的是排序之后,元素所在原来位置的索引
res = arr.argsort()
3、lexsort 按照最后一个数组的规则来排序
十一、数组的去重与重复
unique去重+排序
title重复数组,重复对象为整体
repeat按照列进行重复数据,重复对象为列或行
#axis=1, 按列
res = np.repeat(arr1,2,axis=1)
#axis=0, 按行
res = np.repeat(arr1,2,axis=0)
十二、NumPy 字符串函数
以下函数用于对 dtype 为 numpy.string_ 或 numpy.unicode_ 的数组执行向量化字符串操作。 它们基于 Python 内置库中的标准字符串函数。这些函数在字符数组类(numpy.char)中定义。
函数 | 描述 |
add() | 对两个数组的逐个字符串元素进行连接 |
multiply() | 返回按元素多重连接后的字符串 |
center() | 居中字符串 |
capitalize() | 将字符串第一个字母转换为大写 |
title() | 将字符串的每个单词的第一个字母转换为大写 |
lower() | 数组元素转换为小写 |
upper() | 数组元素转换为大写 |
split() | 指定分隔符对字符串进行分割,并返回数组列表 |
splitlines() | 返回元素中的行列表,以换行符分割 |
strip() | 移除元素开头或者结尾处的特定字符 |
join() | 通过指定分隔符来连接数组中的元素 |
replace() | 使用新字符串替换字符串中的所有子字符串 |
decode() | 数组元素依次调用str.decode |
encode() | 数组元素依次调用str.encode |