一、np.concatenate()函数介绍
在numpy中进行数组拼接,concatenate()函数时最常用的方式之一,这个函数的基本格式是——combined = np.concatenate([array1,array2,…,arrayn],axis)
其中第一个参数以列表的形式“记录”需要进行拼接的数组,第二个参数axis取值为0或者1,表示在数组的哪个“维度”上进行拼接。
二、例子
例1
import numpy as np
a = np.arange(6).reshape((2,3))
b = np.arange(6,12).reshape((2,3))
c = np.arange(12,15).reshape((1,3))
print(a)
print(b)
print(c)
[[0 1 2]
[3 4 5]]
[[ 6 7 8]
[ 9 10 11]]
[[12 13 14]]
combined_1 = np.concatenate([a,b,c],axis=0)
print(combined_1)
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
combined_2 = np.concatenate([a,b],axis=1)
print(combined_2)
[[ 0 1 2 6 7 8]
[ 3 4 5 9 10 11]]
combined_3 = np.concatenate([a,b,c],axis=1)
print(combined_3)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in ()
----> 1 combined_3 = np.concatenate([a,b,c],axis=1)
2 print(combined_3)
ValueError: all the input array dimensions except for the concatenation axis must match exactly
小结:总结一下规律:可以将一个二维数组看成是一个数表或者矩阵,当这样的两个数表或者矩阵进行拼接时,在axis=0的情况下,其实就是将这个数表或者矩阵进行“增行”,也就是列数不变,但是行数增加了。而当axis=1时,就是对这个数表或者矩阵进行“扩列”,也就是行数没有变化,而列数增加了。对应到实际应用中去,前者意味着将数表或矩阵中的样本数量进行增加,但是不改变样本的“字段”(field)数量,后者则表示样本的数量不改变,但是样本的“字段”数量改变,这也就是说,样本所记录的系统信息结构被改变了。
也正因为如此,所以,很显然,当进行“增行”操作时,必须保持拼接的两个数表或者矩阵的“列数”是一致的;而当进行“扩列”时,那么对应地,行数必须是一致的。但是无论如何,首先的条件是,两个数表或者矩阵必须都得是二维的。为了更好的说明这点,我们用下面换一个例子来进行说明。
例2
d = np.array([15,16,17])
print(d)
[15 16 17]
combined_4 = np.concatenate([a,d],axis=0)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in ()
----> 1 combined_4 = np.concatenate([a,d],axis=0)
ValueError: all the input arrays must have same number of dimensions
这就进一步说明,在进行ndarray的拼接时,必须保持数组维度的一致,在这个前提下,再根据需求进行“增行”或者“扩列”
例3(三维情况下,不考虑四维及以上的情况)
a = np.arange(12).reshape((2,2,3))
b = np.arange(12,24).reshape((2,2,3))
c = np.arange(24,30).reshape((2,1,3))
print(a)
print("****************************")
print(b)
print("****************************")
print(c)
[[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]]
****************************
[[[12 13 14]
[15 16 17]]
[[18 19 20]
[21 22 23]]]
****************************
[[[24 25 26]]
[[27 28 29]]]
combine_1 = np.concatenate([a,b],axis=0)
print(combine_1)
[[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]
[[12 13 14]
[15 16 17]]
[[18 19 20]
[21 22 23]]]
combine_2 = np.concatenate([a,b],axis=1)
print(combine_2)
[[[ 0 1 2]
[ 3 4 5]
[12 13 14]
[15 16 17]]
[[ 6 7 8]
[ 9 10 11]
[18 19 20]
[21 22 23]]]
combine_3 = np.concatenate([a,c],axis=0)
print(combine_3)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in ()
----> 1 combine_3 = np.concatenate([a,c],axis=0)
2 print(combine_3)
ValueError: all the input array dimensions except for the concatenation axis must match exactly
combine_4 = np.concatenate([b,c],axis=1)
print(combine_4)
[[[12 13 14]
[15 16 17]
[24 25 26]]
[[18 19 20]
[21 22 23]
[27 28 29]]]
小结:三维的情况下,可能的情况如上述,但不作深入的探讨,因为现实生活中,大部分数据是以矩阵和数表的形式出现的,因此,二维情况下的拼接更有意义。三维的情况作为展示,需要时可以临时研究其变化规律,但总体来说,将其最后一维“降维”成普通的数据元素进行对待即可,其实和二维的规律差不多。
三、np.expand_dims()函数介绍
该函数可以改变数组的维度,对数组进行“扩维”操作,其形式为array_expanded = np.expand_dims(array,axis)
同样的,array表示需要进行“扩维”操作的数组,而axis表示在数组的哪个“维度”上进行扩维。
四、例子
a = np.array([1,2,3,4,5])
print(a)
[1 2 3 4 5]
a_2d_0 = np.expand_dims(a,axis=0)
print(a_2d_0)
[[1 2 3 4 5]]
a_2d_1 = np.expand_dims(a,axis=1)
print(a_2d_1)
[[1]
[2]
[3]
[4]
[5]]
b = np.arange(12).reshape((3,4))
print(b)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
b_2d_0 =np.expand_dims(b,axis=0)
print(b_2d_0)
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]]
b_2d_1 =np.expand_dims(b,axis=1)
print(b_2d_1)
[[[ 0 1 2 3]]
[[ 4 5 6 7]]
[[ 8 9 10 11]]]
结论:同样的,通过观察可以发现,不论是由一维扩展成二维还是由二维扩展成三维,都有一个规律:当axis=0时,其实就是在原数组的基础上直接再加一个中括号(square bracket)即可,而当axis=1时,便是将原来数组中的“第二维”的向量取出(按:读者须要会意“第二维”的含义,其实就是第二个中括号所包含的那个向量),然后对其“扩维”(所谓的扩维其实就是增加一个中括号)即可。
五、两个函数的使用场景
先假设有某数表A为3x3形式,取其第一列A[:,0],第三列A[:,2],再将二者相除,得B=A[:,0]/A[:,2]。此时,显然,B向量表示了原有数表经过计算后的某个系统信息。那么现在的需求就是将其作为列“增加”到原有的数表中去。请问如何操作?show me the code
解:显然这时需要用concatenate方法将AB进行拼接,然而如上所述,当进行“扩列”拼接时,需要保持两个矩阵维度一致以及行数一致。而B显然是一维的,有三个元素的数组,因此也就需要对B使用expand_dims进行“扩维”。最后进行拼接。具体伪代码如下:
B_2d = np.expand_dims(B,axis=1)
combined = np.concatenate([A,B],axis=1)
六、一点补充
关于轴参数axis,在对数组进行数学运算的时候,也是可以使用的,比如
a = np.arange(12).reshape((2,6))
print(a)
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
a.min(axis=1)
array([0, 6])
a.min(axis=0)
array([0, 1, 2, 3, 4, 5])
a.mean(axis=0)
array([3., 4., 5., 6., 7., 8.])
a.mean(axis=1)
array([2.5, 8.5])
结论:在concatenate函数和expand_dims函数中,axis参数为0时,不论是拼接还是扩维,总是对数表按照“横向”进行操作,为1时,则进行“竖向”操作。但当对数组进行数学运算的时候,axis=0则是进行“竖向”操作,axis=1则进行“横向”操作。这二者对该参数的使用是不同的,这点要注意。