Numpy概述
NumPy(Numerical Python的简称)是Python数值计算最重要的基础包。大多数提供科学计算的包都是用NumPy的数组作为构建基础。
Why NumPy?
- 一个强大的N维数组对象ndarray,具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组
- 用于集成由C、C++、Fortran等语言类库的C语言 API
- 线性代数、随机数生成以及傅里叶变换功能。
- 用于对整组数据进行快速运算的标准数学函数(无需编写循环),支持大量的数据运算
- 是众多机器学习框架的基础库
Tips:Python的面向数组计算可以追溯到1995年,Jim Hugunin创建了Numeric库。接下来的10年,许多科学编程社区纷纷开始使用Python的数组编程,但是进入21世纪,库的生态系统变得碎片化了。2005年,Travis Oliphant从Numeric和Numarray项目整了出了NumPy项目,进而所有社区都集合到了这个框架下。
NumPy之于数值计算特别重要的原因之一,是因为它可以高效处理大数组的数据。这是因为:
- NumPy是在一个连续的内存块中存储数据,独立于其他Python内置对象。NumPy的C语言编写的算法库可以操作内存,而不必进行类型检查或其它前期工作。比起Python的内置序列,NumPy数组使用的内存更少。
- NumPy可以在整个数组上执行复杂的计算,而不需要Python的for循环。
测试numpy
我们使用Anaconda工具中的jupyter notebook编辑器进行编写代码:
import numpy as np
x = np.__version__
print(x) # 1.19.1
Python List的特点
- 可重复性
- 索引,切片,连接,查找等
- 多种数据类型
但是其性能不太好。
python中的数组模块array 不支持将数据当做向量或者矩阵,不支持基本运算。
numpy.array
1.numpy.array的创建以及基本使用:
import numpy as nm
# numpy的ndarray对象的创建
a = nm.array([i for i in range(10)])
print(type(a),a) # <class 'numpy.ndarray'> [0 1 2 3 4 5 6 7 8 9]
# 返回元素的类型
x = a.dtype
print(type(x),x) # <class 'numpy.dtype'> int32
# 对象占用字节数量
y = a.nbytes
print(type(y),y) # <class 'int'> 40
# 修改元素
a[5] = 77
print(a) # [ 0 1 2 3 4 77 6 7 8 9]
# 数值是自动转换
a[5] = 6.6
print(a) # [0 1 2 3 4 6 6 7 8 9]
# 自动转换
a[5] = '78'
print(a) # [ 0 1 2 3 4 78 6 7 8 9]
# 报错,使用int函数不能转换
# a[5] = 'a'
# print(a)
其他方式创建array:
- zeros(shape=(x,y)) ------------------ 输出值全0的格式为shape值的数组
# 创建adarray对象zeros方式-----全0
nm1 = nm.zeros(shape=(2,3))
print(type(nm1),nm1,sep='\n')
# <class 'numpy.ndarray'>
'''[[0. 0. 0.]
[0. 0. 0.]]
'''
- ones(shape=(x,y)) ---------------------- 输出值全1的格式为shape值的数组
# 2.创建全1的数组
nm2 = nm.ones(shape=(2,3))
print(type(nm2),nm2,sep='\n')
# <class 'numpy.ndarray'>
# [[1. 1. 1.]
# [1. 1. 1.]]
- full(shape=(x,y),fill_value=p) --------------- 输出值为p的格式为shape值的数组
# 3.创建填充指定元素的数组
nm3 = nm.full(shape=(2,3),fill_value='ABC')
print(type(nm3),nm3,sep='\n')
# <class 'numpy.ndarray'>
# [['ABC' 'ABC' 'ABC']
# ['ABC' 'ABC' 'ABC']]
- arange(start,end,step) ----------------------- 在start和end点之步长为step的数组成的数组
# end,默认start为None
n1 = np.arange(6)
print(n1) # [0 1 2 3 4 5]
# start,end
n2 = np.arange(2,8)
print(n2) # [2 3 4 5 6 7]
# start end step
# 在end为1以内时,是前开后开的,大于等于1时,前开后闭
n3 = np.arange(0.2,0.8,0.2)
print(n3) # [0.2 0.4 0.6 0.8]
n3 = np.arange(0.2,1.4,0.2)
print(n3) # [0.2 0.4 0.6 0.8 1. 1.2]
- linspace(start,end,num) ---------------- 首元素为start,最后一个元素为end,等差数列的元素数量为num,组成一个数组。
'''等差数列'''
# start end num:等差数列元素数量
n = np.linspace(1,25,5)
print(n) # [ 1. 7. 13. 19. 25.]
random
- randint(start,end,size/num) -------------- 在start和end之间随机输出整数,当设置num或者size时,num为输出整数的数量,size为输出数组的格式返回<class 'numpy.ndarray'>,
'''获取随机数'''
# randint(0,end),返回一个整型随机数
ran = np.random.randint(2)
print(ran)
# randint(start,end),返回一个整型随机数
ran1 = np.random.randint(3,6)
print(ran1)
#randint(start,emd,count),返回<class 'numpy.ndarray'>类型----[4 3 4]
ran1 = np.random.randint(3,6,3)
print(ran1,type(ran1))
# 设定输出的格式为随机数组成的2*3的二维数组
ran1 = np.random.randint(3,6,size=(2,3))
print(ran1)
# [[5 3 3]
# [3 5 3]]
- seed(num) ------------ 记录当前随机出来的数值或者数组
# random.seed
# 随机种子:类似于存储当前随机的值或者数组
np.random.seed(1)
ran1 = np.random.randint(3,6,size=(2,3))
print(ran1)
# [[4 3 3]
# [4 4 3]]
- random(size) --------------随机数,默认返回随机数,指定size时,返回size格式的数组
# random.random() :随机数
ran = np.random.random()
print(ran) # 0.12121232432354
# 返回numpy.ndarray类型,指定size格式
ran = np.random.random((3,5))
print(ran)
- normal(loc,scale,size)
loc:float
此概率分布的均值(对应着整个分布的中心centre)
scale:float
此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)
size:
输出的格式,默认为None,只输出一个值
# random.normal():生成高斯分布数据的数组
no = np.random.normal()
print(no) # 0.7299755964138446
# 1:均值,10:标准差 ,40:生成数量
no = np.random.normal(1,10,40)
print(no) # 生成一维数组,数据具有高斯分布
[ 4.72993789 6.33810912 0.08026701 20.13820388 4.3079713
12.41942519 -10.29595159 -7.50052377 10.60820004 -1.17418175
2.58514884 9.73418235 -0.11383371 -9.38038765 -9.09479827
-9.58256562 7.56284079 0.37508407 -16.38654295 2.03162996]
no = np.random.normal(1,10,size=(3,4))
print(no) # 生成二维数组,数据具有高斯分布
[[ 4.46859335 14.67032704 7.73716075 -11.91562703]
[ -7.48243915 -0.66599572 10.17196021 1.80250588]
[ 3.28238773 -7.80476796 3.78128846 0.29843227]]
2.numpy.array的操作
当创建好数组后,可以通过.属性值擦看该数组的基本内容,例如:
- arr.ndim ---------------- 查看数组的维度
- arr.shape -------------- 查看数组的形状
- arr.size ------------------ 查看数组的元素数量
- reshape((x,y)) -------------- 改变数组的形状,但要与元素数量相匹配
import numpy as np
arr = np.arange(12)
print(arr)
'''当前数组对象属性'''
# 数组的维数
nd = arr.ndim
# 当前数组的形状
sha = arr.shape
# 数组元素的个数
siz = arr.size
print(f'数组维度:{nd},数组的形状:{sha},数组中元素的个数:{siz}')
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
# 数组维度:1,数组的形状:(12,),数组中元素的个数:12
# 修改数组的形状
arr = arr.reshape((3,4))
print(arr)
nd = arr.ndim
sha = arr.shape
siz = arr.size
print(f'数组维度:{nd},数组的形状:{sha},数组中元素的个数:{siz}')
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 数组维度:2,数组的形状:(3, 4),数组中元素的个数:12
3.numpy.array的数据访问
数组切片:
一维数组获取元素以及修改元素值:
import numpy as np
arr=np.arange(10)
print(arr)
# [0 1 2 3 4 5 6 7 8 9]
# 切片
# [start,end,step]
a1 = arr[1:5]
print(a1)
# [1 2 3 4]
a2 = arr[1:5:2]
print(a2)
# [1 3]
a3 = arr[:5]
print(a3)
# [0 1 2 3 4]
a4 = arr[3:]
print(a4)
# [3 4 5 6 7 8 9]
# start在后,end在前,步长为负数
a5 = arr[7:4:-1]
print(a5)
# [7 6 5]
# 修改元素值
arr[4] = 100
print(arr)
# [ 0 1 2 3 100 5 6 7 8 9]
# 修改多个元素值
arr[4:6] = 100,190
print(arr)
二维数组获取值:
'''二维数组'''
arr = np.arange(15)
arr = arr.reshape((3,5))
print(arr)
# 获取第一二行中每行前三个
a6 = arr[:2,:3]
print(a6)
# [[0 1 2]
# [5 6 7]]
# 获取第一行的所有步长为2的元素
a7 = arr[1,::2]
print(a7)
# [5 7 9]
# 从后往前的获取所有的行列
a8 = arr[::-1,::-1]
print(a8)
# [[14 13 12 11 10]
# [ 9 8 7 6 5]
# [ 4 3 2 1 0]]
# 获取所有项的第一个元素
a9 = arr[:,0]
print(a9,a9.shape) # 返回一维数组
# [ 0 5 10](3,)
# 将a9变换形状为二维数组 3行一列
a9 = a9.reshape((3,1))
print(a9,a9.shape) # 返回二维数组
# [[ 0]
# [ 5]
# [10]] (3, 1)
二维数组修改值:
# 修改单个元素值
arr[2,4] = 100
print(arr)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [ 10 11 12 13 100]]
# 修改多个元素值
arr[:2,4] = 100,180
print(arr)
# [[ 0 1 2 3 100]
# [ 5 6 7 8 180]
# [ 10 11 12 13 100]]
4.数组切片的深浅拷贝:
一维数组和二维数组一样,这里以二维数组为例:
当对数组中元素切片后,进行操作,会不会影响其原来数组中的元素值呢?
import numpy as np
arr = np.arange(15)
arr = arr.reshape((3,5))
print(arr)
# 截取arr中的部分值
sub1 = arr[:2,:2]
# 整体运算会创建新的数组sub1
sub1=sub1+2
print(sub1)
# [[2 3]
# [7 8]]
# arr不会改变
print(arr)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]]
# 不会创建新数组,直接在arr上进行操作
sub2 = arr[:2,:2]
sub2 +=2 # sub2还是上边的sub2,只是在基础上对数据加2
print(sub2)
print(arr)
# [[2 3]
# [7 8]]
# [[ 2 3 2 3 4]
# [ 7 8 7 8 9]
# [10 11 12 13 14]]
# 不会创建新数组,直接在arr上进行操作
sub3 = arr[:2,:2]
sub3[:,:] = sub3+2 # sub3[:,:]也是对上边的sub3进行整体切片
print(sub3)
print(arr)
# [[ 4 5]
# [ 9 10]]
# [[ 4 5 2 3 4]
# [ 9 10 7 8 9]
# [10 11 12 13 14]]
copy():深拷贝,完全开辟出新的内存数组
# 完全开辟新的内存数组进行操作,与原数组无关
sub4 = arr[:2,:2].copy()
sub4+=100
print(sub4)
print(arr)
# [[104 105]
# [109 110]]
# [[ 4 5 2 3 4]
# [ 9 10 7 8 9]
# [10 11 12 13 14]]
5.numpy.array的形状维度的改变----reshape(重置数组的形状,改变维度)
arr.reshape((row,col)) ,可将其中一个值制为-1,该值有另一个值和数组元素个数确定。
import numpy as np
arr=np.arange(10)
print(arr,arr.shape,arr.ndim)
# [0 1 2 3 4 5 6 7 8 9] (10,) 1
# 修改数组的形状reshape((row,col))
arr1 =arr.reshape((1,10))
print(arr1,arr1.shape,arr1.ndim)
# [[0 1 2 3 4 5 6 7 8 9]] (1, 10) 2
# 确定行数,自动计算每行的数量:reshape((row,-1)),如果除不尽,那么会报错
arr2 =arr.reshape((2,-1))
print(arr2,arr2.shape,arr2.ndim)
# [[0 1 2 3 4]
# [5 6 7 8 9]] (2, 5) 2
# 确定每行的数量,自动获取行数:reshape((-1,col)),如果除不尽,那么会报错
arr2 =arr.reshape((-1,2))
print(arr2,arr2.shape,arr2.ndim)
# [[0 1]
# [2 3]
# [4 5]
# [6 7]
# [8 9]] (5, 2) 2
6.numpy.array的合并和分割
1.合并
采用:concatenate([arr1,arr2,...],axis=0/1)进行合并
一维数组的合并
对于一维数组:axis的值默认为0,表示横向合并,对列进行拼接。
当合并的数组为一维时,横向合并之后只能是一维数组。
除非改变shape转换为二维数组进行操作。
'''一维数组'''
arr1 = np.arange(3)
arr2 = np.arange(4,7)
print(arr1,arr2)
# [0 1 2] [4 5 6]
# 合并两个数组;concatenate([arr1,arr2,arr3,....],axis=0/1)
# 对于一维数组:axis的值默认为0,表示横向合并,对列进行拼接
# 当合并的数组为一维时,横向合并之后只能是一维数组.
arr = np.concatenate([arr1,arr2])
print(arr)
# [0 1 2 4 5 6]
arr = np.concatenate([arr1,arr2],axis=0)
print(arr)
# [0 1 2 4 5 6]
# 也可以合并多个数组
二维数组的合并
对于二维数组:
- axis的值默认为0,表示横向合并,要求数组对象列数相同,
- axis为1时,表示纵向合并,合并数组对象的行数要一样.
'''二维元素的合并'''
# axis的值默认为0,表示横向合并,要求数组对象列数相同,
# axis为1时,表示纵向合并,合并数组对象的行数要一样.
a1 = np.arange(1,9)
a1 = a1.reshape((2,-1))
a2 = np.arange(9,13)
a2 = a2.reshape((-1,4))
print(a1)
print(a2)
# [[1 2 3 4]
# [5 6 7 8]]
# [[ 9 10 11 12]]
# 横向合并,保证列数一样
arr = np.concatenate([a1,a2],axis=0)
print(arr)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
# 纵向合并,保证行数一样
a1 = np.arange(1,9)
a1 = a1.reshape((2,-1))
a2 = np.arange(9,11)
a2 = a2.reshape((-1,1))
arr = np.concatenate([a1,a2],axis=1)
print(arr)
# [[ 1 2 3 4 9]
# [ 5 6 7 8 10]]
合并方法的区分:
- vstack([arr1,arr2,...]) ------- 横向合并
- hstack([arr1,arr2,...]) ------- 纵向合并
'''vstack()和hstack()'''
a1 = np.arange(1,9)
a1 = a1.reshape((2,-1))
a2 = np.arange(9,13)
a2 = a2.reshape((-1,4))
# [[1 2 3 4]
# [5 6 7 8]]
# [[ 9 10 11 12]]
# 横向合并,对行进行合并
arr = np.vstack([a1,a2])
print(arr)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
# 纵向合并,对列进行合并
a2 = np.arange(9,13)
a2 = a2.reshape((2,-1))
arr = np.hstack([a1,a2])
print(arr)
# [[ 1 2 3 4 9 10]
# [ 5 6 7 8 11 12]]
2.分割
一维数组的分割:
split(arr,[分割规则的索引值])
# 一维数组的分割
arr = np.arange(10)
print(arr)
a1,a2,a3 = np.split(arr,[2,6])
print(a1) #[0 1]
print(a2) # [2 3 4 5]
print(a3) # [6 7 8 9]
二维数组的分割
在一维数组的split()基础上加上参数axis值(0/1),控制对行分割还是对列分割。
还可以使用:
- vsplit(arr,[])
- hsplit(arr,[])
进行分割控制选择
# 二维数组的分割
arr = np.arange(16).reshape((4,4))
print(arr)
# 对行进行分割
x1,x2 = np.split(arr,[2],axis=0)
print(x1)
print(x2)
# [[0 1 2 3]
# [4 5 6 7]]
# [[ 8 9 10 11]
# [12 13 14 15]]
# 对列进行分割
x1,x2 = np.split(arr,[2],axis=1)
print(x1)
print(x2)
# [[ 0 1]
# [ 4 5]
# [ 8 9]
# [12 13]]
# [[ 2 3]
# [ 6 7]
# [10 11]
# [14 15]]
# 分割方式的区分
# 对行分割
x1,x2 = np.vsplit(arr,[2])
print(x1)
print(x2)
# 对列分割
x1,x2 = np.hsplit(arr,[2])
print(x1)
print(x2)
7.numpy.array的运算
使用numpy.array要比python中list进行算数运算快很多。并且numpy中的array可以以多种形式存在。
numpy的数组支持整体运算,就时可以直接在数组上进行加减乘除等操作,如果时list的话,要先拆分后计算在合并。
import numpy as np
# ndarray支持整体的算术运算
arr = np.arange(15).reshape(3,5)
print(arr)
# 加法
arr1 = arr+3
print(arr1)
# 整除3
arr2 = arr//3
print(arr2)
# 乘法
arr3 = arr*-1
print(arr3)
# 绝对值
arr4 = np.abs(arr3)
print(arr4)
# sin函数
arr5 = np.sin(arr4)
print(arr5)
还有:
- cos(arr)
- tan(arr)
- arctan(arr)
- exp(arr) ---------取e的arr次方
- exp2(arr)
- np.power(3, arr) ---任何数的arr次方
- log(arr)
- log2(arr)
- log10(arr)
8.矩阵运算
1.矩阵与矩阵的运算
- 对于结构相同的矩阵来说,可以进行加,减,元素乘法,除,点积的运算。
- 对于结构不同的矩阵来说,能进行点积运算。但是要求矩阵之间的行数和列数对应。行数=列数,列数等于行数。
矩阵中的乘法分为元素乘法和矩阵乘法
- 元素乘法-(乘)可以使用:ab或者np.multiply(a,b)
- 矩阵乘法(点乘)可以使用:np.dot(a,b) 或 np.matmul(a,b) 或 a.dot(b) 或 a@b
矩阵乘法-点积的计算规则:第一个矩阵中与该元素行号相同的元素与第二个矩阵与该元素列号相同的元素,第一个与第一个相乘,第二个与第二个相乘,最后相加。a.dot(b) 与 np.dot(a,b)效果相同。
最后还有矩阵的转置运算:将行与列进行交换展示。arr1 = arr.T
1.矩阵的加法,减法 ----- (必须做到矩阵结构相同)
2.对应元素相乘,相除
3.矩阵乘法-----点积dot()
4.矩阵转置
import numpy as np
arr1 = np.arange(1,5).reshape((2,2))
arr2 = np.arange(0,4).reshape((2,2))
print(arr1)
# [[1 2]
# [3 4]]
print(arr2)
# [[0 1]
# [2 3]]
print(arr1+arr2)
# [[1 3]
# [5 7]]
print(arr1-arr2)
# [[1 1]
# [1 1]]
print(arr1*arr2)
# [[ 0 2]
# [ 6 12]]
print(arr1.dot(arr2))
# 计算规则:第一个矩阵中与该元素行号相同的元素与第二个矩阵与该元素列号相同的元素,第一个与第一个相乘,第二个与第二个相乘,最后相加
# 矩阵积计算不遵循交换律,np.dot(a,b) 和 np.dot(b,a) 得到的结果是不一样的
# [[1*0+2*2 1*1+2*3]
# [3*0+2*4 3*1+3*4]]
# [[ 4 7]
# [ 8 15]]
print('*'*50)
arr1 = np.array([[1,2,3,4],[4,5,6,7]])
arr2 = np.array([[1,2],[3,4],[5,6],[7,8]])
# 矩阵相乘
arr3 = arr1.dot(arr2)
print(arr3)
# 转置矩阵
arr = np.arange(1,5).reshape((2,2))
print(arr)
arr = arr.T
print(arr)
2.向量和矩阵的运算
在上边的都是矩阵和矩阵之间的运算,都是二维的,在下边我们计算一维和二维之间的运算,也就是举着你和向量之间的运算。
1.加法
在加法时,首先将一维的向量转为2维的矩阵,也就是将[1,2]转为[[1,2],[1,2]]后,对应元素进行相加。
将一维数组转为二维数组可以使用合并的方法将两个数组合并成矩阵进行加法运算,
也可以使用叠堆的方法进行计算
2.叠堆
tile(arr,(row,col))
A = np.array([1,2])
a = np.tile(A,(2,1)) # 行*2,列不变,*1
print(a)
#array([[1, 2],
# [1, 2]])
a = np.tile(A,(2,3)) # 行*2,列*3
print(a)
#array([[1, 2, 1, 2, 1, 2],
# [1, 2, 1, 2, 1, 2]])
2.乘法
当进行乘法时,第一个的列数要与第二个的行数一致。
在(矩阵*向量)进行运算时,由于向量是一维的(只有一行),要先将向量转换为二维的矩阵[1,2]--->[[1],[2]],然后再按照矩阵之间的点积进行乘法。
3.矩阵的逆
单位矩阵:对角线的值为1,其余的值都为0。
- 任何矩阵 @ 单位矩阵 = 本身
- 矩阵 @ 矩阵的逆 = 单位矩阵
import numpy as np
a = np.arange(4).reshape(2,2)
ani = np.linalg.inv(a)
print(ani)
print(a @ ani)
注意:只有方阵才有逆矩阵(行列相等)
4.矩阵的伪逆
np.linalg.pinv(b):求b的伪逆矩阵
b = np.arange(16).reshape(2,8)
print(b)
bni = np.linalg.pinv(b)
print(bni)
[[ 0 1 2 3 4 5 6 7]
[ 8 9 10 11 12 13 14 15]]
[[-1.35416667e-01 5.20833333e-02]
[-1.01190476e-01 4.16666667e-02]
[-6.69642857e-02 3.12500000e-02]
[-3.27380952e-02 2.08333333e-02]
[ 1.48809524e-03 1.04166667e-02]
[ 3.57142857e-02 -7.30583920e-18]
[ 6.99404762e-02 -1.04166667e-02]
[ 1.04166667e-01 -2.08333333e-02]]
9.numpy中的聚合操作
1.sum
np中的sum是对矩阵中所有元素相加计算的
import numpy as np
arr = np.arange(12)
print(arr)
su = np.sum(arr)
print(su)
arr1 = np.arange(12).reshape(3,4)
print(arr1)
su = np.sum(arr1)
print(su)
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
# 66
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 66
无论是一维还是二维,使用np.sum都是求所有元素的和
而python中的sum在计算矩阵时
对于一维数组:与np.sum一样
对于二维数组:是对每一列相加,返回一个一维数组。
2.max,min
求矩阵中的最小值和最大值。
min = np.min(arr)
print(min)
max = np.max(arr)
print(max)
# 0
# 11
3.prod
求矩阵的乘积
arr = np.arange(1,12)
arr1 = np.arange(12).reshape(3,4)
p = np.prod(arr)
print(p)
p = np.prod(arr1,axis=0)
print(p)
p = np.prod(arr1,axis=1)
print(p)
# 39916800
# [ 0 45 120 231]
# [ 0 840 7920]
3.多维度聚合
在上述的sum,min,max,prod三个聚合函数中,在对二维矩阵操作时,在参数上加上axis的值,进行选择性求值。
对于二维数组:
- 不加axis时,返回所有元素的和,最大值,最小值,返回的类型为numpy.float64
- axis=0时:返回每列的和,最大值,最小值,组成的一维数组
- axis =1时:返回每行的和,最大值,最小值,组成的一维数组
4.其他聚合操作
- np.mean(arr) -------- 求数组/矩阵的平均值,对于二维数组,同样可以使用axis值
- np.median(arr) -------求中位数
- np.percentile(arr,q=) -------求第q%的数据
- np.var(arr) -------------方差
- np.std(arr) ------------标注差
10.索引运算
1.获取最大值最小值的索引
import numpy as np
a=np.array([11,3,5,18])
x=np.argmax(a)
print(x) # 返回数组中最大元素的索引值: 3
y=np.argmin(a)
print(y) #返回的是数组中最小元素的索引值: 1
2.获取数据排序后的索引的排序
sort = np.sort(x) --------对数组进行排序,返回新的数组,对原数组没有影响
x.sort() ------------ 对原数组进行了排序
对于二维数组:
np.sort(x) --------------默认随每行进行排序。
np.sort(x,axis=0) ----------对每列进行排序
np.sort(x,axis=1) ----------对每行进行排序
使用索引进行排序
a=np.array([11,3,5,18])
z = np.argsort(a)
# 返回的是将数组a中的元素按升序排列后对应元素的索引值数组: 【1,2,0,3】
w = np.argsort(-a)
# 返回的是将数组a中的元素按降序排列后对应元素的索引值数组: 【3,0,2,1】
a[z]
# 返回a按升序排列后的数组 : 【3,5,11,18】
a[a[::-1]]
# 返回a按降序排列后的数组: 【18,11,5,3】
np.argsort(arr)对原数组没有操作。
3.分割
- np.partition(x, 3) ------分割,把索引为3的元素作为分隔值,返回一个数组,其前边的值都比该值小,后边的值都比该值大。
np.argpartition(x, 3) ----- 分割索引,在partition的基础上,只是返回的是索引值的分割。
对于二维数组,可以用axis对其进行选择性的分割。
4.花式索引
'''一维数组'''
arr = np.arange(6)
print(arr)
# [0 1 2 3 4 5]
print(arr[1])
# 1
ind = [3, 5]
print(arr[ind])
# [3 5]
# 给出索引的形式为二维数组,根据索引值获取到数据,返回相应的二维数组
ind = np.array([[0, 2], [1, 3]])
print(arr[ind])
# [[0 2]
# [1 3]]
print('*'*50)
'''二维数组'''
arr = np.arange(16).reshape(4,-1)
print(arr)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]
# [12 13 14 15]]
# 利索引获取数据值
row = np.array([0, 1, 2])
col = np.array([1, 2, 3])
print(arr[row, col])
# [ 1 6 11]
# 获取第0行中的1,2,3号索引中的值
print(arr[0, col])
# [1 2 3]
# 获取第0,1行下第1,2,3列
print(arr[:2, col])
# [[1 2 3]
# [5 6 7]]
# 根据bool值决定是否获取
col = [True, False, True, True]
print(arr[0,col])
# [0 2 3]
11.比较
可以对数组中元素进行比较运算,判断该数组中小于某个值的元素,若满足条件,返回True,否则,返回False
import numpy as np
arr = np.arange(16)
print(type(arr<3),arr<3)
# <class 'numpy.ndarray'> [ True True True False False False False False False False False False
# False False False False]
# 使用花式索引取出符合条件的数据
print(arr[arr<3])
print(2 * arr == 24 - 4 * arr)
# [False False False False True False False False False False False False
# False False False False]
# 只有4能满足上述表达式
还有>,>=,<=,==,!=,还可以查看数组中某个元素满足某个表达式成立。
1.使用比较结果进行操作
1.count_nonzero(比较):返回其中Ture的个数
arr = np.arange(16)
bool = arr<3
print(bool)
# [ True True True False False False False False False False False False
# False False False False]
# 在上边返回bool值的基础上,返回Ture的个数(非零数,在python中True为1,Flase为0)
num = np.count_nonzero(bool)
print(num)
# 4
2.sum(): 之和
# 一个True为一个1,sum:所有的True之和
num = np.sum(bool)
print(num)
# 3个元素符合条件
# 所有符合条件的值之和
c = np.sum(arr[bool])
print(c)
# 这三个元素之和为3
对于二维数组,可以按列或者按行符合条件的值的个数进行选择性的统计;都返回一维数组
- 对每列或每行符合条件的值的个数进行返回
- 也可以对所有符合条件的值相加后返回一个数值
arr1 = np.arange(16).reshape(4,4)
print(arr1)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]
# [12 13 14 15]]
bool = arr1%2 ==0
re = np.sum(bool,axis=0)
print(re)
# [4 0 4 0]
re2 = np.sum(bool,axis=1)
print(re2)
# [2 2 2 2]
re = np.sum(arr1[bool])
print(re)
# 56
这些方法中参数条件还可以是逻辑运算与或非:
与:&
arr = np.arange(16)
r = np.sum((arr > 3) & (arr < 10))
print(r)
# 6个元素符合条件
r = np.sum(arr[(arr > 3) & (arr < 10)])
print(r)
# 这6个元素之和为39
或:|
d = np.sum((arr % 2 == 0) | (arr > 10))
print(d)
# 11个符合 0,2,4,6,8,10,11,12,13,14,15
非:~
e= np.sum(~(arr == 0))
print(e)
# 15
3.其他操作:
- np.any(条件)
- np.all(条件)
# 只要有一个满足arr1>0,就返回True
b = np.any(arr1>0)
print(b)
# 所有数据都满足条件时,返回True,否则返回False
c = np.all(arr1>=0)
print(c)
对于二维数组,axis在这两个方法中都可以使用,对行和列进行操作返回。
12.比较结果和花式索引
也就是把比较条件放在arr[条件]中,进行获取数据
arr1 = np.arange(16).reshape(4,4)
# 所有符合%2==0的数据
a= arr1[arr1 % 2 == 0]
print(a)
# arr1[:,3] % 3 == 0 为行,返回的为bool数组。列为该行所有数据
# 所有行的第三个数据分别为3,7,11,15,分别余3,符合条件的为3,15所以返回制为[True,Flase,Flase,True]
# 也就是找出第0行和第三行的的所有数据
u = arr1[arr1[:,3] % 3 == 0, :]
print(u)
[[ 0 1 2 3]
[12 13 14 15]]
网友评论