什么是NumPy?
- Numpy是Python科学计算库,用于快速处理任意维度的数组。
- NumPy提供一个N维数组类型ndarray,它描述了相同类型的“items”的集合。
- numpy.ndarray支持向量化运算。
- NumPy使用c语言写的,底部解除了GIL,其对数组的操作速度不在受python解释器限制。
NumPy和python中的列表有什么区别?
- python一个列表中可以存储多种数据类型。比如a = [1,‘a’]是允许的,而NumPy中的数组只能存储同种数据类型。
- NumPy中的数组可以是多维的,当多维数组中所有的数据都是数值类型的时候,相当于线性代数中的矩阵,是可以进行相互间的运算的。
如何创建一个NumPy数组?
- 根据Python中的列表生成:
import numpy as np
a1 = np.array([1,2,3,4])
print(a1)
- 使用np.arange生成,np.arange的用法类似于Python中的range:
import numpy as np
a2 = np.arange(2,21,2)
print(a2)
(arrange中前两个参数代表列表的区间,第三个参数代表步长,即两个相邻元素之间的差值)
- 使用np.random生成随机数的数组:
a1 = np.random.random(2,2) # 生成2行2列的随机数的数组,元素大小在0-1之间
a2 = np.random.randint(0,10,size=(3,3)) # 元素是从0-10之间随机的3行3列的数组
- 使用函数生成特殊的数组:
import numpy as np
a1 = np.zeros((2,2)) #生成一个所有元素都是0的2行2列的数组
a2 = np.ones((3,2)) #生成一个所有元素都是1的3行2列的数组
a3 = np.full((2,2),8) #生成一个所有元素都是8的2行2列的数组
a4 = np.eye(3) #生成一个对角矩阵,对角线上的元素全为1,其他元素都为0的3x3的矩阵
5. ndarray常用属性:
ndarray.dtype:
- 默认的数据类型:
import numpy as np
a1 = np.array([1,2,3])
print(a1.dtype)
# 如果是windows系统,默认是int32
# 如果是mac或者linux系统,则根据系统来
- 指定dtype
import numpy as np
a1 = np.array([1,2,3],dtype=np.int64)
# 或者 a1 = np.array([1,2,3],dtype="i8")
print(a1.dtype)
- 修改dtype:
import numpy as np
a1 = np.array([1,2,3])
print(a1.dtype) # window系统下默认是int32
# 以下修改dtype
a2 = a1.astype(np.int64) # astype不会修改数组本身,而是会将修改后的结果返回
print(a2.dtype)
ndarray.size:
获取数组中总的元素的个数
import numpy as np
a1 = np.array([[1,2,3],[4,5,6]])
print(a1.size) #打印的是6,因为总共有6个元素
ndarray.ndim:
获取数组的维度
a1 = np.array([1,2,3])
print(a1.ndim) # 维度为1
a2 = np.array([[1,2,3],[4,5,6]])
print(a2.ndim) # 维度为2
a3 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
print(a3.ndim) # 维度为3
ndarray.shape:
获取数组某一维度对应的元组
a1 = np.array([1,2,3])
print(a1.shape) # 输出(3,),意思是一维数组,有3个数据
a2 = np.array([[1,2,3],[4,5,6]])
print(a2.shape) # 输出(2,3),意思是二位数组,2行3列
a3 = np.array([
[
[1,2,3],
[4,5,6]
],
[
[7,8,9],
[10,11,12]
]
])
print(a3.shape) # 输出(2,2,3),意思是三维数组,总共有2个元素,每个元素是2行3列的
a44 = np.array([1,2,3],[4,5])
print(a4.shape) # 输出(2,),意思是a4是一个一维数组,总共有2列
print(a4) # 输出[list([1, 2, 3]) list([4, 5])],其中最外面层是数组,里面是Python列表
ndarray.reshape
修改数组维度
a1 = np.arange(12) #生成一个有12个数据的一维数组
print(a1)
a2 = a1.reshape((3,4)) #变成一个2维数组,是3行4列的
print(a2)
a3 = a1.reshape((2,3,2)) #变成一个3维数组,总共有2块,每一块是2行2列的
print(a3)
a4 = a2.reshape((12,)) # 将a2的二维数组重新变成一个12列的1维数组
print(a4)
a5 = a2.flatten() # 不管a2是几维数组,都将他变成一个一维数组
print(a5)
注意,reshape并不会修改原来数组本身,而是会将修改后的结果返回。如果想要直接修改数组本身,那么可以使用resize来替代reshape。
ndarray.itemsize:
返回数组中每个元素所占字节的大小
a1 = np.array([1,2,3],dtype=np.int32)
print(a1.itemsize) # 打印4,因为每个字节是8位,32位/8=4个字节
**
NumPy数组形状的操作
**
reshape和resize方法:
两个方法都是用来修改数组形状的,但是有一些不同:调用resize()相当于C里面的引用,会导致原数组随之改变
- reshape是将数组转换成指定的形状,然后返回转换后的结果,对于原数组的形状是不会发生改变的。调用方式:
a1 = np.random.randint(0,10,size=(3,4))
a2 = a1.reshape((2,6)) #将修改后的结果返回,不会影响原数组本身
- resize是将数组转换成指定的形状,会直接修改数组本身。并不会返回任何值。调用方式:
a1 = np.random.randint(0,10,size=(3,4))
a1.resize((2,6)) #a1本身发生了改变
flatten和ravel方法:
- flatten是将数组转换为一维数组后,然后将这个拷贝返回回去,所以后续对这个返回值进行修改不会影响之前的数组。
- ravel是将数组转换为一维数组后,将这个视图(可以理解为引用)返回回去,所以后续对这个返回值进行修改会影响之前的数组。
x = np.array([[1, 2], [3, 4]])
x.flatten()[1] = 100 #此时的x[0]的位置元素还是1
x.ravel()[1] = 100 #此时x[0]的位置元素是100
**
不同数组的组合
**
vstack:
将数组按垂直方向进行叠加。数组的列数必须相同才能叠加。
a1 = np.random.randint(0,10,size=(3,5))
a2 = np.random.randint(0,10,size=(1,5))
a3 = np.vstack([a1,a2])
hstack:
将数组按水平方向进行叠加。
a1 = np.random.randint(0,10,size=(3,2))
a2 = np.random.randint(0,10,size=(3,1))
a3 = np.hstack([a1,a2])
concatenate([],axis):
将两个数组进行叠加,但是具体是按水平方向还是按垂直方向。则要看axis的参数,如果axis=0,那么代表的是往垂直方向(一行一行的)叠加,如果axis=1,那么代表的是往水平方向(一列一列的)上叠加,如果axis=None,那么会将两个数组组合成一个一维数组。需要注意的是,如果往水平方向上叠加,那么行必须相同,如果是往垂直方向叠加,那么列必须相同。
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
np.concatenate((a, b), axis=0)
# 结果:
array([[1, 2],
[3, 4],
[5, 6]])
np.concatenate((a, b.T), axis=1)
# 结果:
array([[1, 2, 5],
[3, 4, 6]])
np.concatenate((a, b), axis=None)
# 结果:
array([1, 2, 3, 4, 5, 6])
**
数组的切割:
**
hsplit:
在垂直方向进行切割。用于指定分割成几列,可以使用数字来代表分成几部分,也可以使用数组来代表分割的地方
a1 = np.arange(16.0).reshape(4, 4)
np.hsplit(a1,2) #分割成两部分,把第0,1列和第3,4列分割开
>>> array([[ 0., 1.],
[ 4., 5.],
[ 8., 9.],
[12., 13.]]), array([[ 2., 3.],
[ 6., 7.],
[10., 11.],
[14., 15.]])]
np.hsplit(a1,[1,2]) #代表在下标为1的地方切一刀,下标为2的地方切一刀,分成三部分
>>> [array([[ 0.],
[ 4.],
[ 8.],
[12.]]), array([[ 1.],
[ 5.],
[ 9.],
[13.]]), array([[ 2., 3.],
[ 6., 7.],
[10., 11.],
[14., 15.]])]
vsplit:
在水平方向进行切割。用于指定分割成几行,可以使用数字来代表分成几部分,也可以使用数组来代表分割的地方
np.vsplit(x,2) #代表按照行总共分成2个数组
>>> [array([[0., 1., 2., 3.],
[4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])]
np.vsplit(x,(1,2)) #代表按照行进行划分,在下标为1的地方和下标为2的地方分割
>>> [array([[0., 1., 2., 3.]]),
array([[4., 5., 6., 7.]]),
array([[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])]
plit/array_split(array,indicate_or_seciont,axis)
用于指定切割方式,在切割的时候需要指定是按照行还是按照列,axis=1代表按照列,axis=0代表按照行。
np.array_split(x,2,axis=0) #按照垂直方向切割成2部分
>>> [array([[0., 1., 2., 3.],
[4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])]
数组(矩阵)转置和轴对换:
numpy中的数组其实就是线性代数中的矩阵。ndarray有一个T属性,可以返回这个数组的转置的结果。
a1 = np.arange(0,24).reshape((4,6))
a2 = a1.T
print(a2)
另外还有一个方法叫做transpose,这个方法返回的是一个View,也即修改返回值(即引用),会影响到原来数组
a1 = np.arange(0,24).reshape((4,6))
a2 = a1.transpose()
索引和切片:
- 获取某行的数据
# 如果是一维数组
a1 = np.arange(0,29)
print(a1[1]) #获取下标为1的元素
#如果是二维数组
a1 = np.arange(0,24).reshape((4,6))
print(a1[1]) #获取下标为1的行的数据
- 获取某行某列的数据
a1 = np.arange(0,24).reshape((4,6))
print(a1[1,1]) #获取1行1列的数据
print(a1[0:2,0:2]) #获取0-1行的0-1列的数据(左闭右开)
print(a1[[1,2],[2,3]]) #获取(1,2)和(2,3)的两个数据,这也叫花式索引
布尔索引:
a1 = np.arange(0,24).reshape((4,6))
print(a1<10) #会返回一个新的数组,这个数组中的值全部都是bool类型
> [[ True True True True True True]
[ True True True True False False]
[False False False False False False]
[False False False False False False]]
将a1数组中所有小于10的数据全部都提取出来。那么可以使用以下方式实现:
a1 = np.arange(0,24).reshape((4,6))
a2 = a1 < 10
print(a1[a2]) #这样就会在a1中把a2中为True的元素对应的位置的值提取出来
其中布尔运算可以有!=、==、>、<、>=、<=以及&(与)和|(或)
a1 = np.arange(0,24).reshape((4,6))
a2 = a1[(a1 < 5) | (a1 > 10)]
print(a2)
值的替换:
利用索引,也可以做一些值的替换。把满足条件的位置的值替换成其他的值。
a1 = np.arange(0,24).reshape((4,6))
a1[3] = 0 #将第三行的所有值都替换成0
print(a1)
也可以使用条件索引来实现:
a1 = np.arange(0,24).reshape((4,6))
a1[a1 < 5] = 0 #将小于5的所有值全部都替换成0
print(a1)
还可以使用函数来实现:
# where函数:
a1 = np.arange(0,24).reshape((4,6))
a2 = np.where(a1 < 10,1,0) #把a1中所有小于10的数全部变成1,其余的变成0
print(a2)