数组索引与切片
与python列表相同
一维数组
a1 = np.arange(10)
print(a1)
# 索引操作
print(a1[4])
# 切片操作
print(a1[4:6])
# 使用步长
print(a1[::2])
# 使用负数进行索引
print(a1[-1])
结果:
[0 1 2 3 4 5 6 7 8 9]
4
[4 5]
[0 2 4 6 8]
9
多维数组
a2 = np.random.randint(0,10,size=(4,6))
print(a2)
# 如果二维数组索引只有一个值,那么表示的为行,三维数组只有一个值表示的为块
a2[0] # 第一行
a2[1:3] # 2,3行
a2[[0,2,3]] # 1,3,4行
结果
[[2 0 9 9 5 6]
[9 0 6 2 7 9]
[2 7 5 1 5 2]
[9 9 6 4 8 4]]
[2 0 9 9 5 6]
[[9 0 6 2 7 9]
[2 7 5 1 5 2]]
[[2 0 9 9 5 6]
[2 7 5 1 5 2]
[9 9 6 4 8 4]]
a2[1,1] # 0
a2[[0,2,3],[1,0,3]] # array([0, 2, 4]) (0,1) (2,0) (3,3)
a2[1:3,4:6] # 2~3行的 5~6列
a2[:,1] # 获取一列
a2[:,[1,2,3]]
结果
0
[0 2 4]
[[7 9]
[5 2]]
[0 0 7 9]
[[0 9 9]
[0 6 2]
[7 5 1]
[9 6 4]]
布尔索引
a2 = np.arange(24).reshape((4,6))
print(a2)
print(a2<10)
结果:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
array([[ True, True, True, True, True, True],
[ True, True, True, True, False, False],
[False, False, False, False, False, False],
[False, False, False, False, False, False]], dtype=bool)
返回了一个新的数组,其元素都使bool类型
其中布尔运算可以有 != 、 == 、 > 、 < 、 >= 、 <= 、 & 和 | 。
假要将 a1 数组中所有小于10的数据全部都提取出来。那么可以使用以下方式实现:
print(a2[a2<10])
结果:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
数组值的替换
方法一:
利用索引
a1 = np.random.randint(0,10,size=(3,5))
print(a1)
a1[1] = 0 # 将a1的第二行全部置零
print(a1)
a1[1] = np.array([1,2,3,4,5]) # a1的第二行设置为1~5
print(a1)
结果
array([[8, 9, 2, 2, 0],
[1, 7, 5, 0, 9],
[2, 4, 7, 4, 9]])
array([[8, 9, 2, 2, 0],
[0, 0, 0, 0, 0],
[2, 4, 7, 4, 9]])
array([[8, 9, 2, 2, 0],
[1, 2, 3, 4, 5],
[2, 4, 7, 4, 9]])
方法二:
利用条件索引
a1[a1<3]=1 # a1中小于3的元素替换为1
print(a1)
结果:
array([[8, 9, 1, 1, 1],
[1, 1, 3, 4, 5],
[1, 4, 7, 4, 9]])
方法三:
利用where函数
格式:
new_a = np.where(条件,x,y)
后面的x,y要么都不写要么都写
都不写:
都不写会返回满足条件的下表
都写:
如果满足前面的条件则全部替换成x,否则替换成y
new_a = np.where(a1<5)
print(new_a)
new_a = np.where(a1<5,0,1)
print(new_a)
结果:
(array([0, 0, 0, 1, 1, 1, 1, 2, 2, 2], dtype=int64),
array([2, 3, 4, 0, 1, 2, 3, 0, 1, 3], dtype=int64))
array([[1, 1, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 1]])
广播机制
数组与数的计算:
数组中各个元素都与该数进行计算
a1 = np.random.randint(0,5,size=(3,5))
print(a1)
print(a1*2)
array([[3, 0, 3, 4, 4],
[4, 1, 2, 4, 4],
[1, 1, 1, 3, 0]])
array([[6, 0, 6, 8, 8],
[8, 2, 4, 8, 8],
[2, 2, 2, 6, 0]])
数组与数组的计算
- 结构相同的数组:
两个数组对应位置的元素进行运算
a2 = np.random.randint(0,5,size=(3,5))
print(a2)
print(a1+a2)
array([[1, 1, 2, 0, 4],
[4, 2, 4, 4, 0],
[2, 1, 1, 3, 3]])
array([[4, 1, 5, 4, 8],
[8, 3, 6, 8, 4],
[3, 2, 2, 6, 3]])
- 行数相同列数只有一列或者列数相同行数只有一行
以第一种情况为例:
如果一个数组行列数为34,另一个为31此时行数相同,则可以进行运算,规则为第一个数组的每一行的元素都与第二个数组对应行的元素进行运算。
a4 = np.random.randint(0,5,size=(3,1))
print(a4)
print(a1+a4)
[[0]
[4]
[0]]
array([[3, 0, 3, 4, 4],
[8, 5, 6, 8, 8],
[1, 1, 1, 3, 0]])
第二种情况的规则为第一个数组的每一列的元素都与第二个数组对应列的元素进行计算
注意:
除了上述两种情况,其他结构不同的两个数组无法进行运算
广播原则总结
如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相等或者其中一方的长度为1,则认为他们是广播兼容的,广播会在缺失和(或)长度为1的维度上进行
例如: 两个数组的形状为(3,8,2)和(8,3),从后往前数2,3不相同不能进行运算
两个数组的形状为(3,8,2)和(8,1),从后往前数2,1不相同,但有一方为1,能进行运算
两个数组的形状为(3,1,8)和(8,1),从后往前数8,1不相同,但有一方为1,再向前1,8不同,但也有一方为1,能进行运算
数组形状操作
改变数组形状
方法一:
数组名.reshape(a,b):将数组转换成指定形状,返回转换后的结果,原数组不变
a1 = np.random.randint(0,10,size=(3,4))
print(a1)
a2 = a1.reshape(2,6)
print(a2)
print(a1)
结果:
array([[1, 5, 1, 2],
[1, 5, 8, 6],
[2, 9, 2, 0]])
array([[1, 5, 1, 2, 1, 5],
[8, 6, 2, 9, 2, 0]])
array([[1, 5, 1, 2],
[1, 5, 8, 6],
[2, 9, 2, 0]])
方法二:
数组名.resize(a,b): 不返回任何值,改变原数组本身
a1.resize(4,3)
print(a1)
结果:
array([[1, 5, 1],
[2, 1, 5],
[8, 6, 2],
[9, 2, 0]])
转换为一维数组
方法一:
方法名.flatten():
转换为一维数组后,原数组不会改变,返回值为转为一维数组的拷贝,对返回值进行修改,不影响原数组.
a2 = np.random.randint(0,10,size=(3,4))
print(a2)
a4 = a2.flatten()
a4[0]=100
print(a4)
print(a2)
结果:
array([[2, 0, 1, 3],
[4, 9, 0, 0],
[2, 9, 4, 4]])
[100 0 1 3 4 9 0 0 2 9 4 4]
原数组的第0个位置上的元素没有改变
[[2 0 1 3]
[4 9 0 0]
[2 9 4 4]]
方法二:
方法名.ravel()
转换为一维数组后,原数组不会改变,返回值为视图(可以理解为引用),对返回值进行修改,影响原数组.
a3 = np.random.randint(0,10,size=(3,4))
print(a3)
a5 = a3.ravel()
print(a3)
print(a5)
a5[0]=100
print(a3)
print(a5)
结果
array([[0, 7, 6, 2],
[2, 1, 1, 8],
[5, 9, 7, 5]])
转换一维数组后原数组不发生改变
array([[0, 7, 6, 2],
[2, 1, 1, 8],
[5, 9, 7, 5]])
array([0, 7, 6, 2, 2, 1, 1, 8, 5, 9, 7, 5])
array([[100, 7, 6, 2],
[ 2, 1, 1, 8],
[ 5, 9, 7, 5]])
改变一维数组返回值的同时原数组的元素也跟着发生改变
array([100, 7, 6, 2, 2, 1, 1, 8, 5, 9, 7, 5])
数组叠加
方法一:
np.hstack([a,b]):
列叠加,叠加后两个数组的前后顺序与[]中的顺序相同
b4 = np.random.randint(0,10,size=(3,4))
b5 = np.random.randint(0,10,size=(3,1))
b6 = np.hstack([b5,b4]) # b5在b4前
print(b4)
print(b5)
print(b6)
array([[7, 2, 1, 4],
[6, 8, 0, 5],
[7, 3, 8, 1]])
array([[8],
[7],
[7]])
array([[8, 7, 2, 1, 4],
[7, 6, 8, 0, 5],
[7, 7, 3, 8, 1]])
方法二:
np.vstack([a,b]):
行叠加,结构与列叠加相同
方法三:
np.concatenate([a,b],axis):
如果axis=0则行叠加,如果为1列叠加,如果为None将两个数组组合成一个一维数组
c1 = np.random.randint(0,10,size=(2,4))
c2 = np.random.randint(0,10,size=(1,4))
c3 = np.concatenate([c1,c2],axis=0)
c4 = np.concatenate([c1,c2],axis=None)
print(c1)
print(c2)
print(c3)
print(c4)
结果
array([[8, 7, 5, 3],
[7, 8, 7, 2]])
array([[2, 1, 0, 4]])
array([[8, 7, 5, 3],
[7, 8, 7, 2],
[2, 1, 0, 4]])
array([8, 7, 5, 3, 7, 8, 7, 2, 2, 1, 0, 4])
数组切割
方法一:
np.hsplit(数组名,n/n1,n2)
列切割
hh1 = np.random.randint(0,10,size=(3,4))
np.hsplit(hh1,2) # 平均切割成两部分,平均切割时列数必须能被后面的数字整除
np.hsplit(hh1,(1,2)) # 0~1切一刀,1~2切一刀
array([[9, 2, 8, 6],
[6, 8, 3, 2],
[7, 4, 6, 8]])
[array([[9, 2],
[6, 8],
[7, 4]]),
array([[8, 6],
[3, 2],
[6, 8]])]
[array([[9],
[6],
[7]]),
array([[2],
[8],
[4]]),
array([[8, 6],
[3, 2],
[6, 8]])]
方法二:
np.vsplit(数组名,n/n1,n2)
行切割与上述结构相同
方法三:
split/array_split(array,indicate_or_seciont,axis)
axis=0行,如果为1代表列
ss1 = np.random.randint(0,10,size=(3,4))
np.split(ss1,4,axis=1)
ss2 = np.random.randint(0,10,size=(3,4))
np.split(ss2,3,axis=0)
array([[0, 7, 3, 4],
[7, 2, 9, 7],
[2, 1, 3, 4]])
[array([[0],
[7],
[2]]), array([[7],
[2],
[1]]), array([[3],
[9],
[3]]), array([[4],
[7],
[4]])]
array([[6, 9, 2, 3],
[5, 7, 1, 7],
[3, 8, 3, 3]])
[array([[6, 9, 2, 3]]), array([[5, 7, 1, 7]]), array([[3, 8, 3, 3]])]
数组转置
方法一:
数组名.T
方法二:
数组名.transpose()
tt1 = np.random.randint(0,10,size=(3,4))
tt1.T
tt1.transpose()
array([[7, 8, 9, 0],
[4, 6, 4, 4],
[2, 9, 3, 6]])
array([[7, 4, 2],
[8, 6, 9],
[9, 4, 3],
[0, 4, 6]])
array([[7, 4, 2],
[8, 6, 9],
[9, 4, 3],
[0, 4, 6]])
数组形状操作总结
数组形状改变:
- reshape与resize,前者不改变原数组,有返回值,后者改变原数组,没有返回值
- flatten与ravel, 将数组变为一维数组,不对原数组改变,都有返回值
区别:faltten的返回值是返回的拷贝,对返回值进行操作不影响原数组
ravel返回的原数组时返回的试图,对返回值进行操作影响原数组
数组的组合:
- vstack([]):行叠加,列数必须相同
- hstack([]):列叠加,行数必须相同
- concatenate([],axis),axis=0,行叠加,=1列叠加,=None叠加后变为一维数组,
注意:[a,b],中括号中在前的数组会被叠加到前面(上面)
数组的分割:
- vsplit([],n/(n1,n2)):行切割
- hsplit([],n/(n1,n2)):列切割
注意:如果第二个参数只有一位,则为平均分割,列平均分割时,列数要与n能够整除,否则报错,行分割时,行数要与n能整除否则报错 - split/array_split(array,indicate_or_seciont,axis) :axis=0,行切割,=1列切割。
转置:
- a.T
- a.transpose()