np.hstack(),np.concatenate()与np.stack()是numpy中实现数组拼接的三个函数。
1. np.hsatck(arrays)
np.hstack(arrays)是其中最简单的一个函数。
它接收的参数是一个元组,包含需要组合在一起的几个数组。这些数组需要满足的要求是
例:
a = np.arange(9).reshape(3, 3)
print('a:\n', a)
b = np.arange(12).reshape(3, 4)
print('b:\n', b)
c = np.arange(15).reshape(3, 5)
print('c:\n', c)
print('ab:\n', np.hstack((a, b)))
print('abc:\n', np.hstack((a, b, c)))
输出:
a:
[[0 1 2]
[3 4 5]
[6 7 8]]
b:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
c:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
ab:
[[ 0 1 2 0 1 2 3]
[ 3 4 5 4 5 6 7]
[ 6 7 8 8 9 10 11]]
abc:
[[ 0 1 2 0 1 2 3 0 1 2 3 4]
[ 3 4 5 4 5 6 7 5 6 7 8 9]
[ 6 7 8 8 9 10 11 10 11 12 13 14]]
这个例子相信大家一看就懂,不做赘述。
2. np.concatenate(arrays, axis=0, out=None)
这个函数相当于np.hstack()的扩展。
它接收三个参数:
例:
a = np.arange(8).reshape(2, 2, 2)
b = np.arange(12).reshape(2, 2, 3)
c = np.arange(18).reshape(2, 3, 3)
我们创建了三个数组a,b,c。a和b除2轴外其余维度对应相等,因此a和b可以在2轴方向组合。b和c除1轴外其余维度对应相等,因此a和b可以在1轴方向组合(即水平组合,np.concatenate((a,b),axis=1)与np.hstack((a,b))的效果是等同的)
组合a,b
d = np.concatenate((a, b), axis=2)
print(d, '\n\nshape:', d.shape)
输出:
[[[ 0 1 0 1 2]
[ 2 3 3 4 5]]
[[ 4 5 6 7 8]
[ 6 7 9 10 11]]]
shape: (2, 2, 5)
组合b,c`
e = np.concatenate((b, c), axis=1)
print(e, '\n\nshape:', e.shape)
输出
[[[ 0 1 2]
[ 3 4 5]
[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 6 7 8]
[ 9 10 11]
[ 9 10 11]
[12 13 14]
[15 16 17]]]
shape: (2, 5, 3)
由此可以看出,将多个数组在指定轴上组合后,结果数组除指定轴以外,其余维度元素个数不变,指定轴元素个数为所有参数数组在该轴上元素个数的和。例如,将shape为(2,2,3)的数组与shape为(2,3,3)的数组在1轴方向上组合,结果数组的shape即为(2,2+3,3)。
3. np.stack(arrays, axis=0, out=None)
这是3个函数中最难理解的一个函数。
它接收3个参数:
对于axis参数所指定的内容似乎比较难以理解,但是根据解释,已经可以看到我把这个函数的功能分为了两步:
我们先来看一个例子(A):
a = np.arange(9).reshape(3, 3)
m = a*3
b = np.stack((a, m), axis=1)
print(b, '\n\n', b.shape)
输出:
[[[ 0 1 2]
[ 0 3 6]]
[[ 3 4 5]
[ 9 12 15]]
[[ 6 7 8]
[18 21 24]]]
(3, 2, 3)
这个变化如何实现的?
我们就按照上面说的两个步骤来分解。
首先,对于每个数组,在axis指定轴上增加一维。为了模拟这一步,可以对单个数组进行stack操作。
a = np.arange(9).reshape(3, 3)
m = a
b = np.stack((a,), axis=1)
print(b, '\n\n', b.shape)
输出:
[[[0 1 2]]
[[3 4 5]]
[[6 7 8]]]
(3, 1, 3)
可以看到,在一个shape为(3,3)的数组的1轴上增加一维,其shape就变为(3,1,3),以此类推,如果在一个shape为(3,3)的数组的0轴上增加一维,其shape就变为(1,3,3), 验证一下:
a = np.arange(9).reshape(3, 3)
m = a
b = np.stack((a,), axis=0)
print(b, '\n\n', b.shape)
输出:
[[[0 1 2]
[3 4 5]
[6 7 8]]]
(1, 3, 3)
符合推测。
接着,我们做第二步,在axis指定轴方向上组合数组,这就是concatenate()函数提供的功能。
因此我们可以通过下述操作实现例(A)的等价变换。即:分别再数组a和m的一轴上增加一维,然后让他们在一轴上组合起来。
a = np.arange(9).reshape(3, 3)
m = a*3
b = np.stack((a,), axis=1)
c = np.stack((m,), axis=1)
d = np.concatenate((b,c), axis=1)
print(d, '\n\n', d.shape)
输出
[[[ 0 1 2]
[ 0 3 6]]
[[ 3 4 5]
[ 9 12 15]]
[[ 6 7 8]
[18 21 24]]]
(3, 2, 3)
与例A结果比较,是一致的。
由此我们也可以理解为什么stack()函数要求各数组形状相等,因为concatenate()函数要求各数组除axis指定维度外其余维度元素个数对应相等,而在stack()函数中这条axis指定维度是附加的,并不是参数数组本来的维度。
以上