发布于2020-02-17 21:19 阅读(916) 评论(0) 点赞(25) 收藏(5)
本博客介绍 numpy 模块的使用方法,并对机器学习中应用到的较多的一些方法进行重点讲解。
在机器学习中,用到最多的就是矩阵(数组)的运算了,使用 python 的 list 可以完成这些运算,但是效率不高,使用numpy 提供的函数接口可以很高效的完成这些功能。下面介绍了几种创建 numpy 数组(矩阵) 的方法
import numpy as np
arr=np.array([1,2,3,4],dtype=int)
print(arr)
print(arr.dtype)
arr2=np.array([1,2,3])
print(arr2)
print(arr2.dtype)
arr3=np.array([1,2,3.0])
print(arr3)
print(arr3.dtype)
输出结果:
[1 2 3 4]
int64
[1 2 3]
int64
[1. 2. 3.]
float64
主要参数
import numpy as np
arr=np.asarray([1,2,3,4],dtype=int)
print(arr)
print(arr.dtype)
arr2=np.asarray([1,2,3])
print(arr2)
print(arr2.dtype)
arr3=np.asarray([1,2,3.0])
print(arr3)
print(arr3.dtype)
输出结果:
输出结果:
[1 2 3 4]
int64
[1 2 3]
int64
[1. 2. 3.]
float64
基本用法与 np.array() 一致
import numpy as np
arr1=np.ones(shape=(4,4),dtype=int)
print(arr1)
print("---------------")
arr2=np.zeros(shape=5,dtype=float)
print(arr2)
print("---------------")
arr3=np.full(shape=(2,5),dtype=int,fill_value=520)
print(arr3)
输出结果:
[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]
---------------
[0. 0. 0. 0. 0.]
---------------
[[520 520 520 520 520]
[520 520 520 520 520]]
有三种方法可以生成某一个值的特定矩阵,分别为 np.ones(),np.zeros(),np.full()。三个函数中的参数 dtype 均为可选,判断元素类型的机制和 np.array() 一致。三种函数的用法和返回结果如例所示,理解起来比较简单。
import numpy as np
arr1=np.arange(0,10)
print(arr1)
arr2=np.arange(0,10,0.5)
print(arr2)
arr3=np.linspace(0,10,11)
print(arr3)
输出结果
[0 1 2 3 4 5 6 7 8 9]
[0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8. 8.5
9. 9.5]
[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
np.arange() 可以用于生成等步长的数组,用法类似于 range() ,参数分别为起始点,终止点,步长。终止值不会出出现在最终的数组中。所不同的是步长可以是浮点数,如例子所示。
除了np.arange() 之外,np.linspace() 函数也可以用于生成等步长的数组,与 arange 函数不同的是,生成的数组中包括终止值,第三个参数不是步长,而是平均分成了多少份,如例子所示。
import numpy as np
arr1=np.random.randint(low=0,high=10,size=(2,5))
print(arr1)
arr2=np.random.random(size=(3,3))
print(arr2)
arr3=np.random.normal(loc=0,scale=1,size=20)
print(arr3)
输出结果:
[[2 8 1 2 7]
[6 9 0 3 5]]
[[0.74831657 0.32991162 0.53259451]
[0.7005176 0.17805907 0.58690404]
[0.19568012 0.59133077 0.31332564]]
[-0.16324593 0.12253359 1.2257147 2.35137786 -0.79876596 -0.1480339
1.03034397 0.63034462 0.91966266 -1.24178813 -0.02773027 0.68352114
0.01390874 -0.04098013 0.52609043 -0.83886096 0.07309302 0.49478078
1.7656865 1.1617786 ]
函数 np.random.randint(low,high,size) 用于生成在 low 和 high 之前的一个随机的整数,注意,high 取不到。size 可以是一个整数或者元组,使用整数表示创建一个一位数组,元组表示创建一个shape 为 size 的矩阵。
函数 np.random.random(size) 用于均匀的生成在 0-1 范围内的浮点数。size 的含义和 randint 一致。
函数 np.random.normal(loc,scale,size) 用于生成正太分布的随机数,size 的含义没有变化,loc 表示均值,scale 可以理解为方差,例子中arr3 就是一个均值为0,方差为 1 的正态分布的具有20个元素的数组。
多说一句,计算机中的随机数字不是真正的随机数字,而是使用随机算法生成的伪随机数字,如果想要得到相同的随机数字用于实验的时候复现算法,可以人为的设置随机种子:
np.random.seed(seed) #seed 是一个整数
import numpy as np
arr1=np.random.randint(low=0,high=10,size=(2,5))
print(arr1.shape)
print(arr1.size)
print(arr1.ndim)
print(arr1.dtype)
输出
(2, 5)
10
2
int64
ndim:数组(矩阵)的维度
shape:数组(矩阵)的形状
dtype:数组(矩阵)的数据类型
size:数组中(矩阵)的元素的个数
对于python 的list 数组,我们可以使用 方括号+ 下标的方式进行数据访问。例如一个二维的 python list 数组 arr,可以使用 arr[0][0] 来访问二维数组的第一行,第一列的元素。但是这种方法在 numpy 数组中虽然也可以,但是不建议使用,在numpy 数组中建议使用如下方式访问:
import numpy as np
arr1=np.random.randint(low=0,high=10,size=(2,5))
print(arr1)
print(arr1[1,2])
输出结果:
[[4 5 1 4 0]
[7 4 9 4 7]]
9
arr1[1,2] 表示arr1矩阵的 第第二行,第三列的元素,就是 9 。
除此之外,numpy 还支持切片访问(如果不清楚可以查看Python的基础语法)
import numpy as np
arr=np.array([1,2,3,4,5])
print(arr[:3]) # 访问第四个元素之前的元素(前三个元素)
print(arr[2:]) # 访问第三个元素以及之后的元素
print(arr[0:2]) # 访问第1个元素到第三个元素之间的元素,不包括第三个元素
前面提到过numpy array 不建议使用 arr[索引1][索引2] 来访问二位数组中的元素,为什么呢?其实是容易混淆,下面的例子就演示了这种情况:
import numpy as np
arr=np.random.randint(0,10,size=(5,5))
print(arr)
print("-------------------")
print(arr[:3,:3]) # 取 arr 数组中的 前三行,前三列
print("-------------------")
print(arr[:3][:3]) # 返回的结果是啥?
输出结果:
[[9 2 9 5 8]
[8 3 9 5 5]
[4 7 5 7 2]
[4 2 7 3 3]
[8 8 6 7 7]]
-------------------
[[9 2 9]
[8 3 9]
[4 7 5]]
-------------------
[[9 2 9 5 8]
[8 3 9 5 5]
[4 7 5 7 2]]
是不是觉得很懵? arr[:3][:3] 怎么会返回一个 3行5列的数组呢?其实是 arr[:3] 首先取到了arr 数组的前三行元素,得到了一个中间的数组 arr1,然后 arr1[:3] 又得到了arr1的前三行,最终的结果就是上面展示的那样,看吧,其实 arr[:3][:3] 是对 arr 数组两次取前三行的结果,特别容易混淆,所以,听我一句劝,numpy 数组别用这种双重方括号加索引的方式访问。
特别提醒一下:使用切片的方式得到的子数组其实是对于原数组的引用,修改子数组,原数组也会收到影响,这与python 的list 不同,python list 是默认会复制一个副本到子数组。示例如下:
import numpy as np
arr=np.random.randint(0,10,size=(5,5))
print(arr)
print("-------------------")
subarr=arr[:3,:3]
print(subarr) # 取 arr 数组中的 前三行,前三列
print("--------------------")
subarr[0,0]=250
print(subarr)
print("--------------------")
print(arr)
输出结果:
[[3 6 6 7 8]
[8 7 1 9 2]
[8 6 8 3 3]
[9 5 8 4 2]
[6 0 1 6 0]]
-------------------
[[3 6 6]
[8 7 1]
[8 6 8]]
--------------------
[[250 6 6]
[ 8 7 1]
[ 8 6 8]]
--------------------
[[250 6 6 7 8]
[ 8 7 1 9 2]
[ 8 6 8 3 3]
[ 9 5 8 4 2]
[ 6 0 1 6 0]]
想要建立副本要调用 copy 方法
subarr=arr[:3,:3].copy()
import numpy as np
arr=np.random.randint(0,10,size=25)
print(arr)
print("-------------------")
arr1=arr.reshape(5,5)
print(arr1)
print("--------------------")
print(arr) # 取 arr 数组中的 前三行,前三列
print("--------------------")
arr2=arr.reshape(5,-1)
print(arr2)
print("--------------------")
print(arr.reshape(10,-1))
输出结果:
[2 1 2 2 6 3 4 1 6 7 8 8 4 2 7 2 4 6 8 3 2 3 9 5 8]
-------------------
[[2 1 2 2 6]
[3 4 1 6 7]
[8 8 4 2 7]
[2 4 6 8 3]
[2 3 9 5 8]]
--------------------
[2 1 2 2 6 3 4 1 6 7 8 8 4 2 7 2 4 6 8 3 2 3 9 5 8]
--------------------
[[2 1 2 2 6]
[3 4 1 6 7]
[8 8 4 2 7]
[2 4 6 8 3]
[2 3 9 5 8]]
--------------------
Traceback (most recent call last):
File "/home/qianqianjun/CODE/Python/ML_ Mooc/draw.py", line 3, in <module>
print(arr.reshape(10,-1))
ValueError: cannot reshape array of size 25 into shape (10,newaxis)
reshape(shape) 可以获得形状改变之后的数组,shape 可以是元组,但是可以不写括号
如例子所示,arr1是一个 5 × 5 的矩阵,由原来的数组变换而来。需要注意的是 reshape不会改变原数组,如例子所示。
另外,为了方便起见,numpy 还提供了一种自动计算维度的机制,只要待计算的维度可以唯一确定,numpy 会自动计算,我们只需要填写 -1 即可,如例子所示。
此外,不是随便写啥维度都可以的,必须要可以整除,如例子所示,25 没有办法整除 10,所以 reshape 会报错。
import numpy as np
arr1=np.array([1,2,3])
arr2=np.array([4,5,6])
arr3=np.array([7,8,9])
arr12=np.concatenate([arr1,arr2])
print(arr12)
print("--------------")
arr123=np.concatenate([arr1,arr2,arr3])
print(arr123)
输出结果:
[1 2 3 4 5 6]
--------------
[1 2 3 4 5 6 7 8 9]
对于向量,使用 np.concatenate() 函数即可实现连接合并。参数是要连接的数组,可以是多个。
对于矩阵来说,要比单纯的向量要复杂一点,因为涉及到一个 axis 参数:
import numpy as np
arr1=np.array([[1,2,3]])
arr2=np.array([[4,5,6]])
arr3=np.array([[7,8,9]])
arr12=np.concatenate([arr1,arr2])
print(arr12)
print("--------------")
arr12_=np.concatenate([arr1,arr2],axis=1)
print(arr12_)
print("--------------")
arr123=np.concatenate([arr1,arr2,arr3])
print(arr123)
print("--------------")
arr123_=np.concatenate([arr1,arr2,arr3],axis=1)
print(arr123_)
输出结果:
[[1 2 3]
[4 5 6]]
--------------
[[1 2 3 4 5 6]]
--------------
[[1 2 3]
[4 5 6]
[7 8 9]]
--------------
[[1 2 3 4 5 6 7 8 9]]
axis 默认是 0,按照第一个维度进行拼接,(即按照行进行堆叠)如果是 1 ,就按照第二个维度拼接(即按照列进行堆叠)。如例子所示。
特别注意的是,concatenate 只支持具有相同ndim 的数组进行拼接,下面的例子展示了这种情况
import numpy as np
arr1=np.array([[1,2,3]])
vector=np.array([250,250,250])
arr=np.concatenate([arr1,vector])
输出结果:
Traceback (most recent call last):
File "/home/qianqianjun/CODE/Python/ML_ Mooc/draw.py", line 4, in <module>
arr=np.concatenate([arr1,vector])
ValueError: all the input arrays must have same number of dimensions
对此,numpy 特别的设置了两个很智能的函数 vstack,示例如下:
import numpy as np
arr1=np.array([[1,2,3]])
arr2=np.array([[4,5,6]])
arr3=np.array([[7,8,9]])
vector=np.array([250,250,250])
arrv=np.vstack([arr1,vector])
print(arrv)
输出结果:
[[ 1 2 3]
[250 250 250]]
对于矩阵之间的合并,除了 vstack 之外还有 hstack ,其实和 concatenate函数很类似,vstack 相当于 axis=0,hstack 相当于axis=1。示例如下:
import numpy as np
arr1=np.array([[1,2,3]])
arr2=np.array([[4,5,6]])
arr3=np.array([[7,8,9]])
arrv=np.vstack([arr1,arr2])
arrh=np.hstack([arr1,arr2])
print(arrv)
print("------------------")
print(arrh)
print("------------------")
arrv2=np.concatenate([arr1,arr2],axis=0)
arrh2=np.concatenate([arr1,arr2],axis=1)
print(arrv2)
print("------------------")
print(arrh2)
输出结果
[[1 2 3]
[4 5 6]]
------------------
[[1 2 3 4 5 6]]
------------------
[[1 2 3]
[4 5 6]]
------------------
[[1 2 3 4 5 6]]
使用np.split() 函数来进行数组(矩阵)的分割功能。
import numpy as np
arr=np.random.randint(0,10,size=30)
arr1,arr2,arr3=np.split(arr,[10,20])
print(arr)
print(arr1)
print(arr2)
print(arr3)
输出结果
[8 4 0 8 8 6 5 1 2 5 7 3 0 4 8 3 6 1 2 4 5 3 0 3 4 2 3 6 7 1]
[8 4 0 8 8 6 5 1 2 5]
[7 3 0 4 8 3 6 1 2 4]
[5 3 0 3 4 2 3 6 7 1]
如例子所示,np.split() 按照在隔断点数组中的元素进行分割,将一个长度为 30 的数组分成等长的三部分,只需要添加两个隔断点即可,需要注意的是,隔断点是开区间,这也就是为啥arr1 不包含arr[10] 的原因。
对于 ndim 大于1 的情况,就又涉及到了 axis 参数。示例如下:
import numpy as np
arr=np.random.randint(0,10,size=(10,10))
arr1,arr2,arr3=np.split(arr,[3,6])
print(arr)
print("--------------------------")
print(arr1)
print("--------------------------")
print(arr2)
print("--------------------------")
print(arr3)
print("--------------------------")
arr4,arr5=np.split(arr,[5],axis=1)
print(arr4)
print("--------------------------")
print(arr5)
输出结果:
[[4 3 5 1 6 8 1 8 0 9]
[4 8 1 8 6 1 0 0 2 7]
[1 8 6 2 4 1 5 2 0 4]
[3 7 9 2 2 2 8 6 9 9]
[5 1 9 7 9 0 6 0 3 1]
[8 8 9 2 9 0 8 8 4 2]
[8 1 2 9 2 5 3 1 3 7]
[5 0 9 0 5 1 6 7 7 8]
[1 5 9 5 0 8 1 1 3 2]
[4 3 0 6 4 3 9 4 4 6]]
--------------------------
[[4 3 5 1 6 8 1 8 0 9]
[4 8 1 8 6 1 0 0 2 7]
[1 8 6 2 4 1 5 2 0 4]]
--------------------------
[[3 7 9 2 2 2 8 6 9 9]
[5 1 9 7 9 0 6 0 3 1]
[8 8 9 2 9 0 8 8 4 2]]
--------------------------
[[8 1 2 9 2 5 3 1 3 7]
[5 0 9 0 5 1 6 7 7 8]
[1 5 9 5 0 8 1 1 3 2]
[4 3 0 6 4 3 9 4 4 6]]
--------------------------
[[4 3 5 1 6]
[4 8 1 8 6]
[1 8 6 2 4]
[3 7 9 2 2]
[5 1 9 7 9]
[8 8 9 2 9]
[8 1 2 9 2]
[5 0 9 0 5]
[1 5 9 5 0]
[4 3 0 6 4]]
--------------------------
[[8 1 8 0 9]
[1 0 0 2 7]
[1 5 2 0 4]
[2 8 6 9 9]
[0 6 0 3 1]
[0 8 8 4 2]
[5 3 1 3 7]
[1 6 7 7 8]
[8 1 1 3 2]
[3 9 4 4 6]]
对于 axis参数,已经讲过好多次了,这里不再赘述。
此外,还有两个特定的切分函数,不再赘述了:
up,dowm=np.vsplit(arr,[断点数组]) #垂直方向上进行拆分,相当于 axis=0
left,right=np.hsplit(arr,[断点数组]) #水平方向进行拆分,相当于 axis =1
这里实验数据都是一堆数字,可能不太形象,本人还有一篇博客专门写了维度的切分和合并操作,详见这里:https://blog.csdn.net/qq_38863413/article/details/103526645
这里介绍了numpy数组(矩阵)的一种机制,可以将特定的运算在数组(矩阵)每个元素上执行,不清楚我在说什么可以看下面的例子:
对于有个python 的列表,如果我们想要得到列表中每个元素的2倍 的结果,该如何操作?
L=[1,2,3,4]
print(2*L)
res=[]
for i in L:
res.append(i * 2)
result=[ i*2 for i in L]
print(res)
print(result)
输出结果:
[1, 2, 3, 4, 1, 2, 3, 4]
[2, 4, 6, 8]
[2, 4, 6, 8]
可见,对于每一个元素乘以 2 的任务,python list L 2×L 会复制一遍,两个 L 拼接在一起,无法达到效果,只能使用循环或者列表生成式来计算。而numpy 就不一样,引入universal Function 机制来简化这类操作:
import numpy as np
arr=np.array([1,2,3,4,5])
print(2*arr)
print(10-arr)
print(3+arr)
print(60/arr)
输出结果
[ 2 4 6 8 10]
[9 8 7 6 5]
[4 5 6 7 8]
[60. 30. 20. 15. 12.]
除了支持加减乘除,还支持幂运算(**),取余(%),取倒数(1/arr);三角函数 np.sin(),np.cos() 等,指数和对数函数:np.exp(x),np.power(3,x) 即:x中每一个数字 取 3 的 x[i] 次方,np.log(x),np.log2(x),np.log10(x)……
两个矩阵之间也可以进行这种 universal Function 操作,也就是对应位置的元素进行对应运算:
import numpy as np
arr=np.array([1,2,3,4,5])
arr2=np.array([5,4,3,2,1])
print(arr-arr2)
print(arr+arr2)
print(arr * arr2)
print(arr/arr2)
输出结果:
[-4 -2 0 2 4]
[6 6 6 6 6]
[5 8 9 8 5]
[0.2 0.5 1. 2. 5. ]
需要注意的是,上面提到的 + - × / 两个矩阵 都是对应元素做运算,要求矩阵形状一样,否则会报错。
线性代数中提到的矩阵乘法也在numpy中得到了实现,示例如下:
import numpy as np
arr1=np.array([[1,2,3],[3,2,1]])
arr2=np.array([[4,5],[5,4],[4,5]])
print(arr1.dot(arr2))
输出结果:
[[26 28]
[26 28]]
使用传统的方法代码如下:
import numpy as np
arr1=np.array([[1,2,3],[3,2,1]])
arr2=np.array([[4,5],[5,4],[4,5]])
def multiply(arr1,arr2):
"""
矩阵乘法实现
:param arr1: ndarray
:param arr2: ndarray
:return: arr1.dot(arr2) 的结果
"""
assert arr1.ndim==2 and arr2.ndim==2,"输入数据不是矩阵"
assert arr1.shape[1] == arr2.shape[0],"两个矩阵无法相乘"
res=np.zeros(shape=(arr1.shape[0],arr2.shape[1]),dtype=int)
for i in range(arr1.shape[0]):
for k in range(arr2.shape[0]):
for j in range(arr2.shape[1]):
res[i][j]+= arr1[i][k] * arr2[k][j]
return res
print(multiply(arr1,arr2))
输出结果:
[[26 28]
[26 28]]
可见,numpy 真的很方便。
矩阵转置和求逆矩阵操作也很轻松实现:
import numpy as np
# 求转置矩阵
arr=np.array([[1,2,3],[4,5,6]])
print(arr)
arrT=arr.T
print(arrT)
# 求逆矩阵
arr2=np.array([[1,2],[3,4]])
arr2inv=np.linalg.inv(arr2)
print(arr2)
print(arr2inv)
print(arr2.dot(arr2inv))
输出结果:
[[1 2 3]
[4 5 6]]
[[1 4]
[2 5]
[3 6]]
[[1 2]
[3 4]]
[[-2. 1. ]
[ 1.5 -0.5]]
[[1.00000000e+00 1.11022302e-16]
[0.00000000e+00 1.00000000e+00]]
补充一下,只有方阵才有逆矩阵。
看到这个题目你可能觉得很奇怪,矩阵和向量数学上是不能运算的,没意义。说的没错,确实没意义,这里所说的矩阵和向量运算实际上是想说一下 numpy 的智能之处。如下所示:
import numpy as np
# 矩阵向量相加
arr=np.array([[1,2,3],[4,5,6],[7,8,9]])
vector=np.array([1,2,3])
print(arr+vector)
print("-----------------------------")
# 矩阵向量相乘
arr1=np.array([[1,2,3],[4,5,6],[7,8,9]])
vector1=np.array([3,2,1])
print(arr1.dot(vector1))
print("-----------------------------")
vector1=np.array([3,4,5])
arr2=np.array([[1,2],[2,3],[3,4]])
print(arr2.dot(vector1))
输出结果:
[[ 2 4 6]
[ 5 7 9]
[ 8 10 12]]
-----------------------------
[10 28 46]
-----------------------------
Traceback (most recent call last):
File "/home/qianqianjun/CODE/Python/ML_ Mooc/draw.py", line 16, in <module>
print(arr2.dot(vector1))
ValueError: shapes (3,2) and (3,) not aligned: 2 (dim 1) != 3 (dim 0)
由例子可知:当矩阵和向量进行矩阵乘法运算的时候,numpy 可以自动根据需要智能相乘,但是要要求 矩阵的 shape[1] == 向量的shape[0]。
对于矩阵和向量相加,其实和 universal Function 类似。本质上是先对向量进行堆叠,然后再进行相加,相当于下面的运算:
import numpy as np
arr=np.array([[1,2,3],[4,5,6],[7,8,9]])
vector=np.array([1,2,3])
print(arr+vector)
print("----------------------")
stackV=np.tile(vector,reps=(3,1))
print(stackV)
print("----------------------")
print(arr+stackV)
输出结果:
[[ 2 4 6]
[ 5 7 9]
[ 8 10 12]]
----------------------
[[1 2 3]
[1 2 3]
[1 2 3]]
----------------------
[[ 2 4 6]
[ 5 7 9]
[ 8 10 12]]
其中tail函数用于复制向量,堆叠成数组,reps参数(r,c) 分别表示对于行的维度复制几次,列的维度复制几次。
向量上的聚合运算
np.sum(arr) 或者 arr.sum()
np.min(arr) 或者 arr.min()
np.max(arr) 或者 arr.max()
不再赘述。
矩阵上的聚合运算
np.sum(arr,axis=0) # 每一列相加。 axis=1 的时候每一行相加,即沿着 axis 的方向进行相加。
np.prod(arr) # 所有元素相乘
np.mean() #平均值
np.median() #中位数
np.var() #方差
np.std() #标准差
比较简单,不再赘述。
import numpy as np
arr=np.array([1,2,3,0,4,5,6,520,7,8])
maxIndex=np.argmax(arr)
minIndex=np.argmin(arr)
argIndex=np.argsort(arr)
print("最大值的索引为:"+str(maxIndex))
print("最小值的索引为:"+str(minIndex))
print("排序之后的元素在原数组中的索引分别为:"+str(argIndex))
输出结果:
最大值的索引为:7
最小值的索引为:3
排序之后的元素在原数组中的索引分别为:[3 0 1 2 4 5 6 8 9 7]
np.argmin(arr) 返回arr中最小元素所在的 索引
np.argmax(arr) 返回最大值所在的索引
np.random.shuffle(arr) 打乱arr 的顺序
np.argsort(arr) 返回按照顺序排序之后的元素分别在原来数组中的索引。
对于矩阵,和前面的类似,需要一个 axis 参数:
np.argsort(arr,axis=1) 沿着列进行排序(对每一行分别排序),返回排好序的元素在未排序数组中的索引。axis=0 的时候是沿着 行进行排序(对每一列进行排序)。
这一小节是我觉得 numpy 最方便的地方,很多功能让起初是 Java,C++ 铁杆粉丝的我开始更加喜欢 python。
首先,一个列表可以作为索引,先看一个例子:
import numpy as np
arr=np.array([2,4,6,8,10,12,14,16,18,20])
ind=[3,5,8]
print(arr[ind])
输出结果
[ 8 12 18]
ind=[3,5,8],arr[ind] 返回arr 中的第三个,第五个和第八个元素,十分方便。
这里可以看到,arr[ind] 返回的元素个数就是索引的个数,ind索引数组里面有多少个索引,就从arr 中取到对应位置的元素,组成一个数组返回。
更酷的是ind 甚至可以是 二维的,这样最终的结果是一个二维矩阵。和ind 的shape一样(因为是按照 ind 索引数组中的索引取的元素):
import numpy as np
arr=np.array([2,4,6,8,10,12,14,16,18,20])
ind=np.array([[1,2],[3,4]])
print(arr[ind])
输出结果
[[ 4 6]
[ 8 10]]
还可以这样操作:假设arr 是一个 4 × 4的方阵,如果想得到其中的 (0,1),(1,2),(2,3) 三个点怎么办?
import numpy as np
arr=np.random.randint(0,50,size=(5,5))
row=[0,1,2]
col=[1,2,3]
result=arr[row,col]
print(arr)
print("------------------------")
print(result)
输出结果
[[17 49 4 7 16]
[ 2 16 8 38 44]
[31 22 36 46 33]
[17 23 18 47 26]
[18 8 16 4 14]]
------------------------
[49 8 46]
更加灵活的是 row,col 都可以变换为 数字或者切片操作,例如:
arr[2,col] 固定了行,取到的三个点分别为 (2,1),(2,2),(2,3)
arr[:2,col] 取到 6 个点,分别为 (0,1),(0,2),(0,3),(1,1),(1,2),(1,3)
另外,使用 bool 数组也可以作为 索引,使用bool 数组的意思是当为false 的时候,对于所在的位置不感兴趣:
import numpy as np
arr=np.array([0,1,2,3])
b=[True,True,False,True]
print(arr[b])
输出结果:
[0 1 3]
bool数据有非常大的用处,numpy 的比较运算符返回的是 bool 数组,示例如下:
import numpy as np
arr=np.array([1,2,3,4])
print(arr>3)
print(arr==3)
输出结果:
[False False False True]
[False False True False]
读者可以自己尝试 < , >= , <=,!=等比较运算符。
这里有一个非常好用的写法,比如我想找到一个数组中所有大于 3 的元素,可以这么写:
import numpy as np
arr=np.array([1,2,3,4,5,6,7,8])
print(arr[arr>3])
输出结果:
[4 5 6 7 8]
最后再介绍一下 any 和 all 函数,字面意思很好理解:
np.any(x==0) 如果 x中有一个元素是 0 。则返回为 True;
np.all(x>0) x中必须所有的元素都大于0 才返回 True;示例如下:
import numpy as np
arr=np.array([1,2,3,4,5,6,7,8])
print(np.any(arr>3))
print(np.any(arr>100))
print(np.all(arr<100))
print(np.all(arr>3))
输出结果
True
False
True
False
另外,np.all() 和 np.any() 在处理 二维数组的时候,都可以传入参数 axis,不再赘述了。
作者:vike
链接:https://www.pythonheidong.com/blog/article/231680/975ce7e2fc8590567c6c/
来源:python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!