numpy模块
注:全文中numpy模块名简写为np
一、数组的属性
1、通常来说一个 ndarray 是一个通用的多维数组容器,也就是说,它包含的每一个元素均为相同类型。
2、每一个数组都有一个 shape 属性,它用来表示数组的维度和每一个维度的数量
3、每一个数组都有一个 dtype 属性,用来描述数组的数据类型
4、2 维数组,axis=0,纵轴;axis=1,横轴;如果是 3 维及以上的多维数组,先最外层,然后一层一层按照先横轴再纵轴的逻辑进行匹配轴。
二、数组常见的生成函数
函数 | 描述 |
---|---|
array 函数 | 将输入数据(可以是列表、元组、数组以及其他序列)转换成 ndarray(数组对象),如不显示指明数据类型,将自动推断,默认复制所有输入的数据。 |
asarray 函数 | 将输入转换为 ndarray,如果输入已经是数组则不再进行复制 |
arange 函数 | python 内建函数 range 的数组版,返回一个数组 |
ones | 根据给定形状和数据类型生成全 1 数组 |
ones like | 根据所给的数组生成一个形状一样的全 1 数组 |
zeros | 根据给定形状和数据类型生成全 0 数组 |
zeros_like | 根据所给的数组生成一个形状一样的全 0 数组 |
empty | 根据给定形状生成一个没有初始化数值的空数组 |
empty_like | 根据所给数组生成一个形状一样但没有初始化数值的空数组 |
full | 根据给定的形状和数据类型生成指定数值的数组 |
full_like | 根据所给的数组生成一个形状一样但内容是指定数值的数组 |
eye, identity | 生成一个 N×N 特征矩阵(对角线位置都是 1,其余位置是 0) |
np.random.randn() 函数 | 生成随机正态分布的数据 |
三、数组的类型及类型转换
1、数组的基本类型
类型 | 类型代码 | 描述 |
---|---|---|
int8 uint8 | i1,u1 | 有符号和无符号的 8 数位整数 |
Int16 uint16 | i2,u2 | 有符号和无符号的 16 数位整数 |
int32 uint32 | i4,u4 | 有符号和无符号的 32 数位整数 |
int64 uint64 | i8,u8 | 有符号和无符号的 64 数位整数 |
float16 | f2 | 半精度浮点数 |
float32 | f4 或 f | 标准单精度浮点数,兼容 C 语言 foat |
float64 | f8 或 d | 标准双精度浮点数;兼容 C 语言 double 和 Python float |
float128 | f16 或 g | 拓展精度浮点数 |
complex64 。。。 | c8,c16,c32,c64 | 分别基于 32 位、64 位、128 位、256位浮点数的复数 |
bool | ? | 布尔值,存储 True 或 False |
object | o | Python object 类型 |
string_ | s | 修正的 ASCI 字符串类型:例如生成一个长度为 10的字符串类型,使用’S10’ |
unicode_ | U | 修正的 Unicode 类型,生成一个长度为 10 的Unicode 类型,使用‘U10’ |
2、数组类型的转换
1、 你可以使用 astype 方法显式的转换数组的类型。
eg、a.astype(np.float64) 上述例子中 np.float64 的 np 可以省略书写
2、 也可以使用另一个数组的属性
eg、 a.astype(b.dtype)
3、 在创建数组时直接增加属性(需要使用类型代码)
eg、a.ones((2,3),dtype=’i1’)
3、数组的转置和换轴
注:数组的轴概念,比如一个数组的shape为(2,3,5,6)此数组为一个四维数组,轴0有两个元素,轴1有三个元素,轴2有五个元素,轴3有6个元素。对于实际数组如下图
由下图可以写出4的坐标为(0,1,0,3),2的坐标为(1,0,1,1) ;同列表从0开始
1、转置是一种特殊的数据重组形式,可以返回底层数据的视图而不需要复制任何内容。数组拥有 transpose 方法,也有特殊的 T 属性
a = np.arange(15).reshape(5,3)
print(a.T)
//返回
[[ 0 3 6 9 12]
[ 1 4 7 10 13]
[ 2 5 8 11 14]]
2、对于更高维度的数组,transpose 方法可以接收包含轴编号的元组,用于置换轴(扩展下思维)
b = np.arange(16).reshape((2,2,4))
c = b.transpose((1,0,2))
print(c)
#将轴0和轴1互换,即所有对应坐标进行互换
3、使用.T 进行转置换轴的一个特殊的案例。Ndarray 有一个 swapaxes 方法,该方法接收一对轴编号作为参数,并对轴进行调整用于重组数组
b = np.arange(16).reshape((2,2,4))
c = b.swapaxes(1,2)
print(c)
四、数组的计算
1、常见的数组计算
1、数组的加法:对应位置元素相加,两个数组的shape需要一致
2、数组的乘法 :数组中的每一位元素分别相乘。①、可以数组与数组相乘,②、或者与数字相乘
3、数组的除法:①、数组除数组。②、数组除数字。③、数字除数组
4、数组的布尔运算:两个同尺寸数组比较,每个位置的元素分别比较,返回一个布尔类型
import numpy as np
a = [[1,2,3],[1,2,3]]
b = np.arange(6).reshape(2,3)
a= np.array(a)
#加法
print(a+b)
#乘法
print(a*3)
print(a*b)
#除法
print(a/2)
print(2/a)
print(b/a)
#布尔
print(a==1)
#利用布尔筛选出想要的元素
print(a[a==1])
#利用布尔将数组筛选出的元素重新赋值
a[a==1] = 2
print(a)
5、布尔索引的布尔数组中的数组长度必须和数组轴的长度一致。 还可以使用 != 或在条件表达式前加 ~表示取反,可以使用布尔算数运算符组合多个布尔判断条件
a = ["bog","all","bog","seh","home"]
b = np.array(a)
“bog” == b #返回一个布尔数组
c = np.random.randn(5,3)
#按照布尔值提取数组c中符合的维度(一维就是True位置的元素)
d = c[b=="bog"]
6、按照条件计算数组中符合条件的布尔值
a= np.random.randn(100).reshape(2,50)
print(a)
b=(a>0).sum()
print(b)
注:对于 python 的关键字 and 和 or 对布尔数组并没有用,因此连接条件时使用&(and)和|(or) 进行联结
2、数组常用统计方法
他们可以接收一个可选参数 axis(给定轴),也可默认。
方法 | 描述 |
---|---|
sum | 沿着轴向计算所有元素的累和,0 长度的数组累和为 0 |
mean | 数学平均,0 长度的数组平均值为 NaN |
std,var | 标准差和方差,可以选择自由度调整(默认分母是 n) |
min,max | 最小值和最大值 |
argmin argmax | 最小值和最大值的位置 |
cumsum | 从 0 开始元素累计和 |
cumprod | 从 1 开始元素累计积 |
a = [[1,2,3],[1,2,3]]
a= np.array(a)
print(a.sum())
#等同于
print(np.sum(a))
print(np.sum(a,axis=0))
3、数组常用的一元通用函数
函数 | 描述 |
---|---|
abs、fabs | 逐元素的计算整数、浮点数或者复数的绝对值 |
sqrt | 计算每个元素的平方根(与 arr ** 0.5 相等) |
square | 计算每个元素的平方 |
exp | 计算每个元素的自然指数 e^x |
log、log10、log2、log1p | 分别对应:自然对数(e 为底),对数 10 为底,对数 2 为底,log(1+x) |
sign | 计算每个元素的符号值。正数为 1,负数为-1,0 为 0 |
ceil | 计算每个元素的最高整数值(即大于等于给定值的最小整数) |
floor | 计算每个元素的最小整数值(即小于等于给定元素的最大整数) |
rint | 将元素保留到整数位,并保持 dtype |
modf | 分别将数组的小数部分和整数部分按数组的形式返回(返回两个数组,拿两个变量去接) |
isnan | 返回数组中的元素是否是一个 NaN(不是一个数值,比如负数开方),形式为布尔值数组 |
isfinite、isinf | 分别返回数组中的元素是否有限(非 inf、非 NaN)、是否无限的、形式为布尔数组 |
cos、cosh、sin | 常规的双曲三角函数 |
arccos、arccosh、arcsin、arcsinh,arctan、arctanh | 反三角函数 |
logical_not | 对数组的元素按位取反(与~arr 效果一致) |
np.nan | 构建nan元素 |
4、数组常用的二元通用函数
函数 | 描述 |
---|---|
add | 将数组的对应元素相加 |
subtract | 在第二个数组中,将第一个数组中包含的元素去减,前面去减后面 |
multiply | 将数组中对应的元素相乘 |
divide、floor_divide | 除或整除(放弃余数) |
power | 将第二个数组的元素作为第一个数组对应元素的幂次方 |
maximum,fmax | 逐个元素计算最大值,fmax 忽略 NaN |
minimum,fmin | 逐个元素计算最小值,fmin 忽略 NaN |
mod | 按元素的求模计算(即求除法的余数) |
copysign | 将第一个数组的符号值改为第二个数组的符号值 |
greater、greater_equal,less、less_equal、equal、not_equal | 进行逐个元素的比较,返回布尔值数组(与数学比较符>,>=,<,<=,==,!=效果一致) |
logical_and,logical_or,logical_xor | 逐个进行元素的逻辑操作(与逻辑运算符&,I,^ 效果一致) |
5、常用的线性代数相关函数
1、注:在numpy.linalg拥有一个矩阵分解的标准函数集,以及其他的常用函数 from numpy.linalg import inv,qr …
2、举例:数组的内积 dot 函数。只要是符合数组都可以进行点乘积,二维数组和对于 axis=1 的数组乘积是一个一维数组。可以使用特殊符号@作为中缀操作符进行点乘矩阵操作
a = np.random.randn(10).reshape(2,5)
b = np.random.randn(10).reshape(5,2)
c = a.dot(b)
d = np.dot(a,b)
f = a @ b
#上面三个式子等价
3、常用函数方法
函数 | 描述 |
---|---|
dot | 矩阵的点乘 |
trace | 计算对角元素和 |
det | 计算矩阵的行列式 |
eig | 计算方阵的特征值和特征向量 |
inv | 计算方阵的逆矩阵 |
pinv | 计算矩阵的 moore-penrose 伪逆 |
qr | 计算 OR 分解,等同与前面所说的矩阵分解需要拿两个参数去接 |
svd | 计算奇异值分解(SVD) |
solve | 求解 x 的线性系统 Ax = b ,其中 A 是方阵 |
lstsq | 计算 Ax = b 的最小二乘解 |
五、数组的索引与切片
1、正常索引与切片
a= np.arange(25).reshape(5,5)
#第四行,即轴0上第四行元素
print(a[3])
#第2,3行。即轴0上2-3行元素
print(a[1:3])
#全部行。对轴0
print(a[:])
#第二行第二个元素。即(1,1)
print(a[1,1])#等价于
print(a[1][1])
#第二三行第二三个元素。
print(a[1:3,1:3])#等价于
print(a[1:3][:,1:3])
2、神奇索引:如下面例子;a[[1,2,5]] a[[1,2,5],[1,2,3]] 相当于拿(1,1) (2,2) (5,3) 需要一一对应。每次拿一维或一个。如果不考虑数组的维数,其结果总是一维的。
a= np.arange(30).reshape(6,5)
print(a[[1,2,5]])
print(a[[1,2,5],[1,2,3]])
3、需要注意与切片不同,神奇索引总是将数据复制到一个新的数组中。思考 a[[1,2,5]] [: ,[123]]
4、神奇索引的等效替换
①、
a = np.arange(20).reshape(4,5)
b = a[[2,0,3,1]]
#等效于
c = a.take([2,0,3,1],axis=0)
②、
a[[1]] = 0
#等效于;不接受axis参数,默认先给数组降解到一维(C顺序),
在进行操作,后面的参数可以一一对应[2,2,2,2,2]
a.put([5,6,7,8,9],2)
六、使用数组进行面向数组编程
1、meshgrid 函数接收两个一维数组,并根据两个数组的所有(x,y)对生成一个二维矩阵。一横生成(行),一竖生成(列)
a= np.arange(-5,5,1)
xs , ys = np.meshgrid(a,a)
print(xs)
print(ys)
2、np.where 函数是三元表达式的向量化版本。假设我们有一个布尔值数组,两个数值数组
a= np.array([1.1,1.2,1.3,1.4,1.5])
b=np.array([2.1,2.2,2.3,2.4,2.5])
c = np.array([1,2,1,1,2])
d = (1 == c)
result = [(x if c else y) for x,y,c in zip(a,b,d)]
print(result) #[1.1, 2.2, 1.3, 1.4, 2.5]
等同于
a= np.array([1.1,1.2,1.3,1.4,1.5])
b=np.array([2.1,2.2,2.3,2.4,2.5])
c = np.array([1,2,1,1,2])
d = (1 == c)
result = np.where(d,a,b)
print(result)
对于上述的描述中 np.where 的第二个和第三个参数并不需要是数组,他们可以是标量。 where 在数据分析中的一个典型的用法是根据一个数组来生成一个新的数组。
七、唯一值与其它集合逻辑
方法 | 描述 |
---|---|
unique | 返回的是数组唯一值排序后形成的数组。即去重的效果,可以对任意类型的数组进行操作 |
intersect1d(x,y) | 计算 x 和 y 的交集,并排序 |
union1d(x,y) | 计算 x 和 y 的并集,并排序 |
in1d(x,y) | 计算 x 中的元素是否包含在 y 中,返回一个布尔数组 |
setdiff1d(x,y) | 差集,在 x 中但不在 y 中的 x 的元素 |
setxor1d(x,y) | 异或集,在 x 或 y 中,但不属于 x、y 交集的元素 |
八、数组重塑
1、 reshape() 方法 也可以使用 a.reshape().reshape()
2、 使用 ravel 和 flatten 将数组扁平化(即降维) 。如果结果中的值在原始数据中是连续的,则 ravel 不会生成底层数值的副本,而 flatten 一定生成底层数据的副本。可以接收一个 order 参数,用来表示在数组中使用哪种顺序(C,F,A,K),默认使用 C 顺序
3、 查阅资料学习 C 顺序和·Fortran 顺序 ,堆叠数组
C 顺序/行方向顺序,首先遍历更高的维度(例如,在轴 0 上行进之前先在轴 1 上行进)
F 顺序/列方向顺序,首先遍历更低维度(例如,在轴 1 上行进之前先在轴 0 上行进)
a = np.random.normal(size=(2,3))
b = np.zeros((3,3))
c = np.r_[a,b]
print(c)沿着axis=0堆叠,最低维度
a = np.ones((2,3,2))
b = np.zeros((2,3,2))
#沿着axis=dtype(1)堆叠,最高维度
c = np.c_[a,b] print(c)
#注:如果是一维数组则r_表示axis=0,即竖轴
4、重复元素复制或堆叠
①、repeat 方法: 按照规定进行复制,对于多维数组要确定轴
a = np.array([1,2,3,4,5])
b = a.repeat(3) #对整体规定次数
c= a.repeat([2,1,2,3,1]) #分别对每个元素规定次数
②、tile 方法: 按照轴的方向堆叠副本,在视觉上你可以将他看成铺垫瓷砖
a = np.array([1,2,3,4,5])
b = np.zeros((5)) print(np.tile(a,2))
d = np.vstack([a,b])
c = np.tile(d,(2,3)) #行2次列三次
#高维用dtype形式来表示
print(c)
九、数组的连接
1、concatenate 可以将数组按照约定轴的顺序进行合并
a = np.random.normal(size=(5,4))
b = np.zeros((5,3))
c = np.concatenate([a,b],axis=1)
print(c)
2、vstack,row_stack: 按行堆叠数组
3、hstack :按列堆叠数组
4、column_stack : 类似于 hstack,但会首先把一维数组转换为 2 维列向量
5、dstack : 按“深度”堆叠数组(沿着轴 2)
6、split: 沿着指定的轴,在传递位置上分割数组
x = np.arange(9)
np.split(x,3)
np.split(x,[3,5,6,10]) #下标
np.split(x,(3,)) #元组
np.split(x,1,axis=0) #按哪个轴
7、hsplit、vsplit : 分别沿着轴 0 和轴 1 进行分隔的方便函数
十、数组的排序
1、sort 方法直接对原数组进行排序。
a= np.random.randn(10).reshape(2,5)
print(a)
a.sort(1) #按哪一个轴
print(a)
2、对已排序数组寻找元素坐标
a = np.array([1,3,5,8,9])
b = a.searchsorted(7) #返回7应该插入的坐标
print(b)
c = a.searchsorted([2,0,11])
print(c) #返回应该插入位置坐标的数组
3、间接排序
argsort 和 np.lexsort()
values = np.array([5,0,1,3,2])
indexer = values.argsort()
print(indexer)#[1 2 4 3 0]
c = values[indexer]
print(c)#[0 1 2 3 5]
4、部分排序
numpy.partition 和 numpy.argpartition,用于围绕第 k 个最小元素对数值进行分区 。更多请查阅链接https://blog.csdn.net/weixin_37722024/article/details/64440133
a= [1,4,12,34,12,31,5,1,32,12,1,7,9]
a = np.array(a)
indices = np.argpartition(a,3)
print(indices)
#[ 0 7 10 1 6 5 4 3 8 9 2 11 12]
#只把第四小的元素找出
print(a[indices[3]]) # 第四小的元素为
#也可以同时排出多个
indices = np.argpartition(a,[2,3])
十一、伪随机数生成
1、 numpy.random 模块填补了 python 中内建 random 模块的不足
2、 你可以使用 normal 获取一个固定尺寸的正态分布的样本
a = np.random.normal(size=(5,4))
print(a)
#上面等同于 np.random.rangn(20).reshape(5,4)
3、创建一个随机数生成器。
eg、rng = np.random.RandomState(1,2,3,4)
4、 常用的 np.random 函数
函数 | 描述 |
---|---|
seed | 向随机数生成器传递随机状态种子 |
permutation | 返回一个序列的随机排列,或者返回一个乱序的整数范围序列 |
shuffle | 随机排列一个序列 |
rand | 从均匀分布中抽取样本 |
randint | 根据给定的由低到高的范围抽取随机整数 |
randn | 从均值 0 方差 1 的正态分布中抽取样本 |
binomial | 从二项分布中抽取样本 |
normal | 从正态(高斯)分布中抽取样本 |
beta | 从 beta 分布中抽取样本 |
chisquare | 从卡方分布中抽取样本 |
gamma | 从伽马分布中抽取样本 |
uniform | 从平均[0,1)分布中抽取样本 |
十二、使用数组进行文件输入和输出
1、 np.save , np.load 是高效的存取硬盘数据的两大工具函数,数组在默认模式下是按照压缩的格式进行存储的,后缀名为.npy
2、 使用 np.savez 将多个元组压缩储存在文件中。需要添加索引 key 方便下次取用
3、 使用 np.save_compressed 将新的元组放到已经压缩的文件中
a= np.random.randn(1000).reshape(20,50)
b = a*10
np.save("yyy",b) #‘yyy’为文件名,b为要存的数组
c= np.load("yyy.npy") #读取
np.savez("zzz.npz",a=a,b=b)#需要加索引key方便下次读取
c = np.load("zzz.npz")
print(c['a'])
#向已有文件继续向内存储
np.savez_compressed('zzz.npz',d = a)
c = np.load("zzz.npz")
print(c['d'])
十三、其它
1、不使用科学计数
np.set_printoptions(suppress=True)
2、 给nan元素赋值为0
array[ np.isnan(array) ] = 0
3、筛掉nan
array[~ np.isnan(array) ]