像上篇最后说的,“轴”概念是numpy中很重要的概念。对一个ndarray来说,轴用0,1,2,...,n-1表示。
轴既代表数组颗粒度的大小,从0轴到n轴颗粒度递增,即数组单位越来越小。
同时,“轴”又可以理解为对ndarray的shape(1,2,3,...,n)的索引,0轴指向了1。
回顾完轴的概念,我们开始今天的学习。
拼接与分割都是调用不同的方法。
拼接
拼接数组和序列,浅记一下:
方法 | 描述 | 常用的参数 |
---|---|---|
np.concatenate() | (数组)拼接在指定轴之后 |
多个数组的元组; axis: 指定拼接的轴 |
np.stack() | (数组)拼接在新轴之后 |
多个数组的元组; axis: 指定的基准轴,用于调整拼接的颗粒度 |
np.hstack() | (数组)拼接在行上(水平拼接) | / |
np.vstack() | (数组)拼接在列上(垂直拼接) | / |
np.concatenate()方法:(数组)拼接在指定轴之后
- 多个数组的元组;
- axis: 指定拼接的轴。
import numpy as np
arr1 = np.arange(12).reshape(3,4)
arr2 = np.ones(12).reshape(3,4)
concatenate_it_axis0 = np.concatenate((arr1,arr2), axis=0) # 指定在0轴上拼接,即行延续
concatenate_it_axis1 = np.concatenate((arr1,arr2), axis=1) # 指定在1轴上拼接,即列延续
print('concatenate_it_axis0的拼接效果:\n', concatenate_it_axis0)
print('concatenate_it_axis1的拼接效果:\n', concatenate_it_axis1)
# 运行结果:
concatenate_it_axis0的拼接效果:
[[ 0. 1. 2. 3.]
[ 4. 5. 6. 7.]
[ 8. 9. 10. 11.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]
concatenate_it_axis1的拼接效果:
[[ 0. 1. 2. 3. 1. 1. 1. 1.]
[ 4. 5. 6. 7. 1. 1. 1. 1.]
[ 8. 9. 10. 11. 1. 1. 1. 1.]]
np.stack()方法:(数组)拼接在新轴之后
- 多个数组的元组;
- axis: 指定的基准轴,用于调整拼接的颗粒度。
这个方法抽象一点。我们试着理解一下:
由于stack()方法是增加新轴,所以对于一个shape(b,a)而言,新数组的shape其实为(c,b,a)。
axis参数的书写标准也在于此,用以指定数据拼接时的颗粒度大小,即对于shape(b,a):
axis=0:增加新轴,块块拼接(直接以增加新轴的方式对两个数组拼接)
axis=1:增加新轴,行行拼接
axis=2:增加新轴,列列拼接
思考一下,如果是拼接两个数组的shape(c,b,a),axis怎么写呢?
没错,stack()后的数组,其shape就变成了(d,c,b,a),所以axis的效果就像这样:
axis=0:增加新轴,大块进行拼接(也相当于两个数组直接拼接)
axis=1:增加新轴,块块拼接
axis=2:增加新轴,行行拼接
axis=3:增加新轴,列列拼接
是的,其实不难理解。
结合例子看下:
import numpy as np
arr1 = np.arange(12).reshape(3,4)
arr2 = np.ones(12).reshape(3,4)
atack_it_axis2 = np.stack((arr1,arr2), axis=2) # 增加新轴,列列拼接
atack_it_axis0 = np.stack((arr1,arr2), axis=0) # 增加新轴,直接拼接
atack_it_axis1 = np.stack((arr1,arr2), axis=1) # 增加新轴,行行拼接
print('atack_it_axis2,增加新轴的拼接数组:\n',atack_it_axis2)
print('atack_it_axis0,增加新轴的拼接数组:\n',atack_it_axis0)
print('atack_it_axis1,增加新轴的拼接数组:\n',atack_it_axis1)
# 运行结果:
atack_it_axis2,增加新轴的拼接数组:
[[[ 0. 1.]
[ 1. 1.]
[ 2. 1.]
[ 3. 1.]]
[[ 4. 1.]
[ 5. 1.]
[ 6. 1.]
[ 7. 1.]]
[[ 8. 1.]
[ 9. 1.]
[10. 1.]
[11. 1.]]]
atack_it_axis0,增加新轴的拼接数组:
[[[ 0. 1. 2. 3.]
[ 4. 5. 6. 7.]
[ 8. 9. 10. 11.]]
[[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]]
atack_it_axis1,增加新轴的拼接数组:
[[[ 0. 1. 2. 3.]
[ 1. 1. 1. 1.]]
[[ 4. 5. 6. 7.]
[ 1. 1. 1. 1.]]
[[ 8. 9. 10. 11.]
[ 1. 1. 1. 1.]]]
无论是np.concatenate()还是np.stack(),拼接一个数组,要求两个拼接的对象的维度要相同。
这很好理解,因为不同维度的错误拼接就像这张图一样:
维度错误的数组拼接.png
np.hstack()水平拼接(延续列)和np.vstack()垂直拼接(延续行)就没什么好讲的,直接传入数组就行。np.concatenate()方法同样能完成这些操作。
分割
方法 | 描述 | 常用的参数 |
---|---|---|
np.split() | 沿指定轴切分 |
ary: 要分割的数组; axis: 指定分割的轴 |
np.hsplit() | (数组)按轴水平分割 |
ary: 要分割的数组; axis: 指定分割的轴 |
np.vsplit() | (数组)按轴垂直分割 |
ary: 要分割的数组; axis: 指定分割的轴 |
用一个例子看看np.split()的操作,其他的用法类似就不多讲了:
import numpy as np
arr1 = np.arange(16).reshape(4,4)
res1, res2 = np.split(arr1, 2) # 平均2等分,按行(axis不写默认=0)
print('arr1:\n', arr1)
print('arr1切开前半段:\n', res1)
print('arr1切开后半段:\n', res2)
# 运行结果:
arr1:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
arr1切开前半段:
[[0 1 2 3]
[4 5 6 7]]
arr1切开后半段:
[[ 8 9 10 11]
[12 13 14 15]]
arr1 = np.arange(16).reshape(4,4)
res1, res2 = np.split(arr1, 2, axis=1) # 平均2等分,按列
print('arr1:\n', arr1)
print('arr1切开前半段:\n', res1)
print('arr1切开后半段:\n', res2)
# 运行结果:
arr1:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
arr1切开前半段:
[[ 0 1]
[ 4 5]
[ 8 9]
[12 13]]
arr1切开后半段:
[[ 2 3]
[ 6 7]
[10 11]
[14 15]]
arr1 = np.arange(16).reshape(4,4)
res1, res2 = np.split(arr1, 3) # 平均3等分。分不成三块,报错
print('arr1:\n', arr1)
print('arr1切开前半段:\n', res1)
print('arr1切开后半段:\n', res2)
# 运行结果:
报错
arr1 = np.arange(16).reshape(4,4)
res1, res2 = np.split(arr1, [1]) # 切第一行与后面几行
print('arr1:\n', arr1)
print('arr1切开前半段:\n', res1)
print('arr1切开后半段:\n', res2)
# 运行结果:
arr1:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
arr1切开前半段:
[[0 1 2 3]]
arr1切开后半段:
[[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
arr2 = np.arange(12)
res1, res2 = np.split(arr2, indices_or_sections=[3]) # 按元素切。指定的元素在后面数组的第一位
print('arr1:\n', arr2)
print('arr1切开前半段:\n', res1)
print('arr1切开后半段:\n', res2)
# 运行结果:
arr1:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
arr1切开前半段:
[0 1 2]
arr1切开后半段:
[ 3 4 5 6 7 8 9 10 11]
网友评论