numpy入门总结
一、背景
在模型转换的过程中常常接触到numpy这个科学计算库,如果对这个库不熟悉,就会使我们的转换工作效率变的低效,次文档总结一些常用到的numpy使用方法,以供后期小伙伴们查阅学习。
二、numpy的数组创建和查看类型
1、np.array()方法,直接传数组,即列表
import numpy as np
t1 = np.array([1,2,3,4])
print(t1, type(t1)) # [1 2 3 4] <class 'numpy.ndarray'>
t2 = np.array(range(10))
print(t2) #[0 1 2 3 4 5 6 7 8 9]
2、np.arange()
t3 = np.arange(10)
print(t3)
3、类型查看
print(t3.dtype)
# int64计算机是64位就是int64
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUWjdGNc-1583937234850)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200310110534653.png)]
4、指定生成的类型
t4 = np.array(range(4),dtype='i1')
print(t4,t4.dtype)
# [0 1 2 3] int8
5、生成bool类型
t5 = np.array([1,0,1,0],dtype=bool)
print(t5,t5.dtype)
# [ True False True False] bool
6、调整数据类型
t6=t4.astype("int16")
print(t6,t6.dtype)
# [0 1 2 3] int16
7、取小数
# 取小数
import random
print(random.random()) # 0.17211585028793763
# 指定生成float32的小数
t7 = np.array([random.random() for i in range(10)],dtype='f4')
print(t7, t7.dtype)
'''
[0.9527267 0.58131206 0.69266117 0.35412568 0.9847397 0.37631688
0.45819402 0.3455826 0.71597284 0.9252038 ] float32
'''
# 指定保留的小数位数
print(round(random.random(),3))
# 0.623
t8 = np.round([random.random() for i in range(10)],3)
print(t8,t8.dtype)
'''
[0.443 0.093 0.563 0.563 0.188 0.095 0.589 0.422 0.209 0.565] float64
'''
三、numpy数组的形状
Np.shape()
1、一维数组
t1 = np.array([1,2,3,4])
print(t1) # [1 2 3 4]
2、二维数组
t2 = np.array([[1,2,3,4],[1,2,3,4]])
print(t2, t2.shape) # (2, 4)
'''
[[1 2 3 4]
[1 2 3 4]]
'''
print(f'维度是{t2.ndim}') # 2
3、三维数组
t3 = np.array([[[1, 2, 3, 4], [5, 6, 7, 8],[0,9,8,7]],[[1, 2, 3, 4], [5, 6, 7, 8],[0,9,8,7]] ])
print(t3)
'''
[[[1 2 3 4]
[5 6 7 8]
[0 9 8 7]]
[[1 2 3 4]
[5 6 7 8]
[0 9 8 7]]]
'''
print(f'维度是{t3.ndim}') # 3
print(t3.shape) # (2, 3, 4),2表示三维里的‘块’,3表示3行,4表示4列,一共是2x3x4=24个元素
4、np.reshape()
t4 = t3.reshape((4,3,2))
print(t4)
print(t4.shape) # (4,3,2)
'''
[[[1 2]
[3 4]
[5 6]]
[[7 8]
[0 9]
[8 7]]
[[1 2]
[3 4]
[5 6]]
[[7 8]
[0 9]
[8 7]]]
'''
5、多维变一维
# 注意元祖中为1个元素才为1维
t5 = t3.reshape((24,))
print(t5)
#[1 2 3 4 5 6 7 8 0 9 8 7 1 2 3 4 5 6 7 8 0 9 8 7]
print(t5.ndim) # 1
# 如果写reshape((21,1))
t5 = t3.reshape((24,1))
print(t5)
'''
[[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[0]
[9]
[8]
[7]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[0]
[9]
[8]
[7]]
'''
print(t5.ndim) # 2
# 写成reshape((1,24))
t5 = t3.reshape((1,24))
print(t5)
'''
[[1 2 3 4 5 6 7 8 0 9 8 7 1 2 3 4 5 6 7 8 0 9 8 7]]
'''
print(t5.ndim) # 2
6、不知道到多维数组的具体维数时的转化为一维
# 先查看原数组的shape的长度
b = len(t3.shape)
s = 1
for i in range(b):# 获取总的元素个数
s = s * t3.shape[i]
t6 = t3.reshape((s,))
print(t6)
7、将多维数组展开,多维转一维
t7 = t3.flatten()
print(t7,t7.ndim)
四、计算
1、加,减,乘,除都是每个元素都做相应的运算,前提是shape一样
2、广播原则
如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为他们是广播兼容的,广播会在缺失和(或)长度为1的维度上进行
理解:
可以把维度指的是shape所对应的数字个数
例如:
shape为(3,3,2)的数组能够和(3,2)的数组进行计算
五、数组的索引和读取
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uLmUGRWH-1583937234854)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200310161205328.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDeduRUz-1583937234859)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200310161245261.png)]
1、numpy读取数据
CSV:Comma-Separated Value,逗号分隔值文件
显示:表状态
源文件:换行和逗号分隔行列的格式化文本每一行的数据表示一条记录
np.loadtxt(frame, dtype=np.float, delimter=None,skiprows=0,usecols=None,unpack=False)
unpack有转置的效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8xU4wALj-1583937234860)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200310162633112.png)]
2、numpy的转置
t1 = np.arange(24).reshape((4,6))
print(t1)
'''
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
'''
方法1:
t2 = t1.T
print(t2)
'''
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
'''
方法2:
t3 = t1.swapaxes(1,0)
print(t3)
'''
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
'''
方法3:
t4 = t1.transpose()
print(t4)
'''
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
'''
3、numpy的取值
宗旨就是区分逗号前后的行和列。具体的值的取法跟python列表取值相同
v1 =t1[0,1] # 第一行第二列的数字
v2 = t1[[0,3],] # 取第一行和第四行的所有数据
v3 = t1[:, [0,3]] # 取不连续的多列
# 取连续多行
v = t1[0:3,:]
# # 取连续多列
v = t1[:,0:3]
# 取行和列的交叉点
v = t1[0:3,[0,3]]# 一到三行的第一个和第4个元素
4、numpy的clic裁剪
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N6gW4cg6-1583937234862)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200310225919386.png)]
#将数组中小于10的替换成10,大于18的替换成18
nan:not a number表示不是一个数字
#什么时候numpy中会出现nan:
当我们读取本地的文件为float的时候,如果有缺失,就会出现nan
当做了一个不合适的计算的时候(比如无穷大(inf)减去无穷大)
inf(-inf,inf):infinity,inf表示正无穷,-inf表示负无穷
#什么时候回出现inf包括(-inf,+inf)
比如一个数字除以0,(python中直接会报错,numpy中是一个inf或者-inf)
那么如何指定一个nan或者inf呢?
注意他们的type类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x9DEO0BR-1583937234868)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200310230132008.png)]
5、nan
#1、两个nan是不相等的
print(np.nan==np.nan) # False
#2、np.nan!=np.nan
print(np.nan!=np.nan) # True
#3 判断数组中nan的个数
t = np.array([1.,2.,0])
a = np.nan
t1 = np.hstack((t,a))
print(t1,type(t1))
'''
[ 1. 2. 0. nan] <class 'numpy.ndarray'>
'''
print(np.count_nonzero(t1!=t1))# 1 统计nan的个数
#4、nan和任何值计算都是nan
#5、通过np.isnam(a)来判断,返回bool类型,比如将nan变为0
print(np.isnan(t))#[False False False True]
t1[np.isnan(t1)]=0
print(t1)# [1. 2. 0. 0.]
# 等价
t[[False, False, False, True]] = 0
print(t) #[1. 2. 0. 0.]
5.1替换nan的影响
那么问题来了,在一组数据中单纯的把nan替换为0,合适么?会带来什么样的影响?
比如,全部替换为0后,替换之前的平均值如果大于0,替换之后的均值肯定会变小,所以更一般的方式是把缺失的数值替换为#均值(中值)或者是直接删除有缺失值的一行
5.2、替换nan为均值
t = np.arange(24).reshape((4, 6)).astype('float')
t[[2, ], [1, 2, 3]] = np.nan
'''
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[12. nan nan nan 16. 17.]
[18. 19. 20. 21. 22. 23.]]
'''
# 方法1
def func(t):
for i in range(t.shape[1]):
nan_num = np.count_nonzero(t[:, i] != t[:, i])
if nan_num > 0: # 有nan值
# 计算其余值的和
now_col = t[:, i]
# now_col_not_nan = now_col[np.isnan(now_col)==False].sum()
nean_now_col_not_nan = np.mean(now_col[np.isnan(now_col) == False])
# 将均值赋值给nan
now_col[np.isnan(now_col)] = nean_now_col_not_nan
return t
# 方法2
def func1(t):
for i in range(t.shape[1]):
nan_num = np.count_nonzero(t[:, i] != t[:, i])
if nan_num > 0:
now_col = t[:, i]
sum_now_col_not_nan = now_col[np.isnan(now_col) == False].sum()
# 求均值
mean_now_col = sum_now_col_not_nan / (np.count_nonzero(now_col == now_col))
now_col[np.isnan(now_col)] = mean_now_col
t[:, i] = now_col
return t
#方法3
def func2(t):
for i in range(t.shape[1]):
nan_num = np.count_nonzero(t[:, i] != t[:, i])
if nan_num > 0:
now_col = t[:, i]
sum_now_col_not_nan = now_col[np.isnan(now_col) == False].sum()
# 求均值
mean_now_col = sum_now_col_not_nan / (t.shape[0]-nan_num)
now_col[np.isnan(now_col)] = mean_now_col
t[:, i] = now_col
return t
5.3几个重要的API
1、numpy.isnan()得到结果是bool值构成的数组,type类型是numpy.ndarray
2、numpy.count_nonzero()统计True或者False的个数
六、numpy的运算
1、numpy的三元运算
t = np.arange(24).reshape((4,6))
print(t)
'''
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
'''
t1 = np.where(t<10,0,20)
print(t1)
'''
[[ 0 0 0 0 0 0]
[ 0 0 0 0 20 20]
[20 20 20 20 20 20]
[20 20 20 20 20 20]]
'''
2、numpy中常用的统计函数
1)求和:t.sum(axis=None)
2)均值:t.mean(a,axis=None)
3)中值:t.median(t,axis=None)
4)最大值:t.max(axis=None)
5)最小值:t.min(axis=None)
6)极值:np.ptp(t,axis=None)即最大值和最小值之差
7)标准差:t.std(axis=None)
六、数组的拼接和行列交换
1、水平拼接
Np.hstack(t1,t2)
2、竖直拼接
Np.vstack(t1,t2)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pnswnhqJ-1583937234871)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200311211703067.png)]
3、行列交换(参照python的值交换)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UylJoZp4-1583937234872)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200311212032110.png)]
七、numpy生成随机数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cHviL8ZF-1583937234878)(/Users/bobwang/Library/Application Support/typora-user-images/image-20200311215021001.png)]
1、np.random.rand(3),产生d0-dn维度的均匀分布的随机数数组,浮点数,范围从0-1
array([0.4537743 , 0.12218856, 0.19139615])
2、np.random.randn(3)产生d0-dn维度的标准正态分布的随机数,浮点数,平均数0,标准差1
array([-1.98484544, -0.33500624, 0.85452387])
3、np.random.randint(1,10,(3,3)) 不包含10,从给定上下限范围选取随机数整数,范围是low,high,形状是shape
array([[2, 7, 3],
[9, 0, 1],
[3, 0, 6]])
4、np.random.uniform(low, high,(size))产生具有均匀分布的数组,low起始值,high是结束值,size是形状
np.random.uniform(0,10,3)
# array([6.41300655, 2.29984067, 3.26329888])
np.random.uniform(0,10,(3,3))
'''
array([[9.2584874 , 1.41935169, 6.15730783],
[4.91354423, 2.38873746, 7.16855836],
[9.12312401, 9.49142017, 8.09919336]])
'''
5、 np.random.normal(loc,scale,(size))从指定正态分布中随机抽取样本,分布中心是loc(概率分布的均值),标准差是scale,形状是size
np.random.normal(0,1,(3,3))# 概率分布的平均数是0,标准差是1,大小size是3x3=9,
'''
array([[ 1.00340979, -0.27594381, -0.52222732],
[-0.11778472, -0.34024685, -0.12298493],
[-0.76679358, -0.12936196, 0.93463417]])
'''
6、np.random.seed(s)随机数种子,s是给定的种子值(随便设置),因为计算机生成的是伪随机数,所以通过设定相同的随机数种子,可以每次生成相同的随机数
for i in range(3):
np.random.seed(1)
t = np.random.randint(0,10,(3,3))
print(t)
'''
[[5 8 9]
[5 0 0]
[1 7 6]]
[[5 8 9]
[5 0 0]
[1 7 6]]
[[5 8 9]
[5 0 0]
[1 7 6]]
'''
八、numpy的补充方法
1、获取最大值最小值的位置
#1 np.argmax(t,axis=0)
注意nan即是最大也是最小
#2 np.argmin(t,axis=1)
2、创建一个全是0的数组
np.zeros((3,4))
'''
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
'''
3、一个全是1的数组
np.ones((3,4))
'''
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
'''
4、创建一个对角线为1的正方形
np.eye(3)
'''
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
'''
九、numpy的copy和view
1、a=b完全不复制,a和b相互影响
2、a=b[:],视图view的操作,一种切片,会创建新的对象a,但是a和b也相互影响,a的数据完全是由b保管,他们两个的数据变化是一致的
3、a=b.copy(),复制深拷贝,a和b互不影响