更新
2021-10-22 更新:
感谢用户lioyeeee
的勘误, 修改了np.arange
函数的输出结果和np.ndarray的ndim
属性拼写错误两部分
Numpy数组的操作
概述
上一章讲解了Numpy入门所必备的一些基础知识.
Numpy中的数组是Numpy的一个名为numpy.ndarray的对象.
因此对于每一个数组,具有这个对象的属性和方法
本章就将讲解Numpy数组创建等操作相关的方法以及数组具有的一些属性.
本章内容有:
- Numpy数组创建的方法
- Numpy数组的属性
- Numpy数组的索引
Numpy数组的创建
Numpy中数组的创建主要的集中方法将在下面进行介绍
numpy.array方法
numpy.array方法主要是用于生成用户自己输入的数组,
一般都是生成比较小的数组
import numpy as np
array_1=np.array([1,4,2,5,3])
print(array_1)
>>>[1,4,2,5,3]
需要注意的是,运用.array方法创建数组时候,所有数据会按照C语言中自动类型转换转换成所有数据中最高级的
例如:
import numpy as np
array_1=np.array([1,3.14,4,6.2])
print(array_1)
>>>[1. ,3.14 ,4. ,6.2 ]
可以用参数dtype来指明数组的数据类型(Numpy的数据类型将在后面介绍)
import numpy as np
array_1=np.array([1,2,3,4,5],dtype='float32')
print(array_1)
>>>[1. ,2. ,3. ,4. ,5. ]
numpy.zeros方法
numpy.zeros方法用于生成用户指定大小的数组,且每项的值都为0
一般多用于自动生成大型数组
import numpy as np
array_1=np.zeros(10,dtype=int)
print(array_1)
>>>[0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0]
同样我们可以改变第一个参数,来生成多维数组
生成多维数组
import numpy as np
array_1=np.zeros((X1,X2,...,Xn),dtype=int)
>>>生成大小为X1×X2×...×Xn的n维数组
numpy.ones方法
和numpy.zeros一模一样,只不过生成的是全为1的数组,这里就不再赘述.
numpy.full方法
numpy.full方法是按照用户的要求的大小,生成一个值全为用户确定的数组
import numpy as np
array_1=np.full((3,4),3.14)
>>>生成一个3×4,值全为3.14的数组
numpy.arange方法
numpy.arange方法按照步长生成一维数组
import numpy as np
array_1=np.arange(0,20,5)
>>>array=[0, 4, 8, 12, 16]
numpy.linspace方法
numpy.linspace方法是按照要求生成所有值均匀分布于两数间的一维数组
import numpy as np
array_1=np.linspace(0,1,5)
>>>array_1=[0. ,0.25 ,0.50 ,0.75 ,1.]
numpy.random.random方法
numpy.random.random方法用于创建指定大小的随机数组,范围在(0,1)之间
import numpy as np
array_1=np.random.random((3,3))
>>>生成3×3大小的分布在(0,1)之间的数组
numpy.random.randint方法
numpy.random.randint方法用于生成分布在指定区间的指定大小的随机整数数组
import numpy as np
array_1=np.random.randint(0,10,(3,3))
>>>生成分布在(0,10)之间的3×3随机数组
numpy.random.normal方法
numpy.random.normal方法用于生成指定均值,方差,大小的随机数组
import numpy as np
array_1=np.random.normal(0,1,(3,3))
>>>生成均值为0,方差为1的3×3矩阵
numpy.eye方法
numpy.eye方法用于生成指定大小的单位阵
import numpy as np
array_1=np.eye(3)
>>>生成3×3的单位阵
numpy.empty方法
numpy.empty用于生成指定大小的空数组
import numpy as np
array_1=np.empty((3,4))
print(array_1)
>>>
[[2.87539110e-248 3.48968839e-313 1.68400738e-019 1.87526075e-177]
[2.00420845e-312 8.36324508e-299 2.01813149e-284 5.65622866e+303]
[2.97157807e-236 7.25962663e-299 7.31075892e-304 3.11334933e+053]]
注意:值数据单元未初始化的结果
Numpy数组的属性
Numpy的数组具有一些属性,具体包括数组的大小,形状,储存大小和数据类型.下面将一一介绍.
下面关于Numpy数组属性的介绍,将基于下面三个数组
import numpy as np
np.random.seed(0) #设置一个随机种子,让下面每个随机数组得到的结果都一样
array_1=np.random.randint(10,size=6) #生成具有六个分布在[0,10)之间的一维随机数组
array_2=np.random.randint(10,size=(3,4)) #生成一个3×4,分布在[0,10)之间的二维随机数组
array_3=np.random.randint(10,size=(3,4,5)) #生成一个3×4×5,分布在[0.10)之间的二维随机数组
数组的维度ndim
每个数组都具有维度,数组的维度就是就是数组的维数.
我们可以通过numpy.ndarray中ndim这个属性来查询
数组名.ndim
例如:
print(array_1.ndim)
print(array_2.ndim)
print(Array_3.ndim)
>>>1
>>>2
>>>3
数组形状shape
每个数组都具有一定的形状.即每个维度的大小
我们可以通过numpy.ndarray中的shape属性来查询
数组名.shape
例如:
print(array_1.shape)
print(array_2.shape)
print(array_3.shape)
>>>(6,)
>>>(3,4)
>>>(3,4,5)
数组的大小size
数组中所有数据的个数称为数组的大小
可以使用numpy.ndarray的size属性来查询
数组名.size
例如:
print(array_1.size)
print(array_2.size)
print(array_3.size)
>>>6
>>>12
>>>60
数组的数据类型dtype
我们在前面讲过,numpy中的数据数据类型
可以通过numpy.ndarray的dtype属性查询
数组名.dtype
例如:
print(array_1.dtype)
print(array_2.dtype)
print(array_3.dtype)
>>>int32
>>>int32
>>>int32
数组元素的字节大小itemsize
由于Python是用C语言写得.
Numpy为了提高运行速率自己重新构造了数据类型并且留下了Python调用的API
所以Numpy中的数据其实就和C语言的类似,都是直接在内存上的输入
我们就可以查询每个numpy数据占内存空间的大小
可以通过numpy.ndarray的itemsize属性来查询数组每个元素的字节大小
数组名.itemsize
例如:
print(array_1.itemsize)
print(array_2.itemsize)
print(array_3.itemsize)
>>>4
>>>4
>>>4
数组的字节大小nbytes
数组的每个元素具有大小,所以数组整体也就具有大小
可以通过numpy.array的nbyte属性来查询
数组名.nbytes
例如:
print(array_1.nbytes)
print(array_2.nbytes)
print(array_3.nbytes)
>>>24
>>>48
>>>240
Numpy数组的索引
Numpy中的数组本质上是列表的嵌套,不过Numpy去掉了Python每个对象复杂的指针
Numpy为Python中留了Python的API,所以我们可以通过索引来获取特定的元素
一维数组
一维数组的索引和Python中的索引一样,只需要用偏移量即可
数组名[偏移量]
例如:
print(array_1[0])
当然也可以使用负索引来从后往前取
print(array_1[-1])
多维数组
Numpy中多维数组的索引就和Python不一样
数组名[第一维偏移量,第二维偏移量,...,第n维偏移量]
例如:
print(array_2[0,1])
print(array_3[1,2,3])
同样,也可以使用负索引从后往前去
结合赋值语句,我们就可以修改数组中的元素的元素值
Numpy数组的切片
上面说的Numpy的索引主要是获取某一个元素.
有的时候我们希望生成Numpy数组的局部.这个时候就可以用切片来完成
不过需要说明的是,通过切片的得到的并不是原数组的副本,而是原数组的视图.
即对切片得到的"子数组"的操作都会修改原数组.
如果我们需要得到副本,那么将视图赋给一个变量即可.
一维数组
Numpy一维数组的切片和Python列表的切片几乎一致
数组名[起始偏移量:终止偏移量:步长]
其中:
- 省略掉起始偏移量表示从第一个元素开始切片.省略掉终止偏移量表示切片到最后一个元素.省略步长表示依次选取
- 起始偏移量和终止偏移量都可以是负数,表示从后往前索引.步长为负数表示从后往前索切片
例如:
print(array_1[:3:2])
array_1_sub=array_1[1:3] #切片操作得到的子数组可以赋值给另外一个数组
多维数组
多维数组的切片和一维数组类似,不过对于各个维度之间的切片用逗号分开
数组名[第一维起始偏移量:第一维终止偏移量:第一维步长,....,第n维起始偏移量:第n维终止偏移量:第n维步长]
对与一维数组适用的操作,多维数组也能用
不过需要注意的是,第一个维度是列
例如:
print(array_2[1:2,1:3])
print(array_3[1:2,1:2,3:4])
副本视图的创建
上面讲到通过对原数组的切片操作得到的是原数组的视图,而非副本.
这个时候即便我们将视图赋给一个新的变量,这个新的变量依旧是原数组的视图而非副本.
所以我们就需要使用numpy.ndarry的copy()方法来创建副本
数组名[切片].copy
数组的变形
对数组的操作除了通过索引得到元素值和通过索引得到数组的视图外,另外一种操作就是对数组进行变形操作.
这种操作也非常有用.例如,在进行图像处理的时候,我们可以通过这样的方式创造出一个掩码,来实现对打码.或者是创建一个从一到九的行向量,然后变形成一个3×3的方阵.
reshape方法
Numpy中数组的变形可以靠numpy.ndarray对象中的reshape方法
数组名.reshape((第一维长度,第二维度长度,...,第n维长度))
需要说明的是:
- 变形前后的数组元素数量一定要相等
- reshape方法会得到一个非副本视图,即对reshape后的数组操作会反映到原数组上.
例如:
print(array_1.reshape((3,3)))
print(array_2.reshape(6))
# 我们经常用的另外一个操作是
grid=np.arange(1,10).reshape(3,3)
切片时使用np.newaxis关键字
切片时候使用newaxis关键字.这个方法主要是将一维的数组转化为二维的行向量或者是列向量.
数组名[np.newaxis,:] #将原数组转化为一个二维的行向量
数组名[:,np.newaxis] #将原数组转化为一个二维的列向量
例如:
array_1[np.nexaxis,:]
array_1[:,np.newaxis]
数组的拼接
除了数组的变形之外,有的时候我们还需要对数组进行拼接.
对数组进行拼接具有三个函数:numpy.concatenate(),numpy.vstack()和numpy.hstack()
numpy.concatenate()函数
numpy.concatenate函数用于沿指定方向拼接数组
np.concatenate([数组1,数组2,...,数组n],axis=指定轴)
其中:
- 拼接的数组在指定方向上的大小一致才能够被拼接到一起.
- axis=0表示沿竖直方向拼接,axis=1表示沿水平方向拼接,n=n表示沿n方向拼接
当拼接的数组为一维时,x=0表示沿水平方向拼接
numpy.vstack()函数
numpy.vstack函数用于在垂直方向上拼接数组.类似于numpy.concatenate()函数中指定axis=0
np.vstack([数组1,数组2,...,数组n])
和numpy.concatenate()函数一样,使用numpy.vstack()函数时候在水平方向上长度必须相等.
例如:
print(np.vstack(array_1,array_1))
numpy.hstack()函数
numpy.hstack()函数用于在水平方向上拼接数组.类似于numpy.concatenate()函数中指定axis=1
np.hstack([数组1,数组2,...,数组n])
一样,这n个数组都必须要在竖直方向上大小相同,否则会报错
数组的分裂
与拼接过程相反的是分裂,类似于数组的拼接,数组的分裂也具有三个函数.分别是:numpy.spilt(),numpy.vsplit(),numpy.hsplit()
numpy.spilt()函数
numpy.split()函数用于沿指定方向,在指定索引出分裂数组
np.split(数组名,[分裂点1,分裂点2,...分裂点n],axis)
需要说明的是:
- numpy.split()函数会返回n+1个数组(都是numpy.ndarray对象)
所以可以用n+1个变量来储存 - axis=0表示竖直方向分裂,axis=1表示水平方向分裂.
例如:
array_1_left,array_1_middle,array_1_right=np.split(array_1,[3,6],axis=0)
array_1[:,np.newaxis]
array_1_upper,array_1_middle,array_1_lower=np.split(array_1,[3,6],axis=1)
numpy.vsplit()函数
numpy.vsplit()函数用于在竖直方向上分裂数组
np.vsplit(数组名,[分裂点1,分裂点2,...,分裂点n])
同样,会返回n+1个数组
例如:
array_1_upper,array_1_lower=np.vsplit(array_1.reshape(10,1),[3])
numpy.hsplit()函数
numpy.hsplit()函数用于在水平方向上分裂数组
np.hsplit(数组名,[分裂点1,分裂2,...,分裂点3])
同样,会返回n+1个数组
例如:
array_1_left,array_1_right=np.hsplit(array_1,[3,5])
array_1_left,array_1_middle,array_1_right=np.split(array_1,[3,6],axis=0)
array_1[:,np.newaxis]
array_1_upper,array_1_middle,array_1_lower=np.split(array_1,[3,6],axis=1)
#### numpy.vsplit()函数
numpy.vsplit()函数用于在竖直方向上分裂数组
```python
np.vsplit(数组名,[分裂点1,分裂点2,...,分裂点n])
同样,会返回n+1个数组
例如:
array_1_upper,array_1_lower=np.vsplit(array_1.reshape(10,1),[3])