文章目录
合并
方法 | 含义 |
---|---|
append | 将值附加到数组的末尾。 |
concatenate、ma.concatenate | 沿现有轴连接一系列数组。保存输入的mask。 |
stack | 沿新轴堆叠一系列数组。 |
block | 从块组合数组。 |
hstack | 沿水平折叠(沿第二维) |
vstack | 垂直顺序排列阵列(沿第一维) |
dstack | 按深度顺序排列数组(沿第三维) |
In [1]: import numpy as np
append
np.append(arr,values,axis=None)
append是将值添加到数组arr
副本的末尾,如果指定arr
,其中values
是和arr
相同形状的。如果未指定axis
则会默认展平为一维数组。值得注意的是append
不会就地发生,而是分配并填充了一个新数组。 因此,在速度上并不是很快。
默认情况下:
In [2]: a = np.arange(12).reshape(2,3,2)
In [3]: b = np.arange(3)
In [4]: np.append(a,b)
Out[4]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 0, 1, 2])
有轴axis
的情况下:
我们可以看到如果制定了轴,上面的a
、b
合并时会报错。这是因为除了指定的轴外,b
上的其它轴必须一致才可以。
In [7]: np.append(a,b,axis = 1)
ValueError: all the input arrays must have same number of dimensions
# a的shape是(2,3,2)、所以如果在axis = 1上合并,
# 则b的shape必须是(2,x,2)的样式,x为正整数即可。
In [8]: b = np.arange(4).reshape(2,1,2)
In [9]: np.append(a,b,axis = 1)
Out[9]:
array([[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 0, 1]],
[[ 6, 7],
[ 8, 9],
[10, 11],
[ 2, 3]]])
# 例如下面定义a(1,2),则如果想在axis = 0插入,
# 则b邀为(x,2)的数组才可以
In [13]: a = np.arange(2).reshape(1,2)
In [14]: b = np.arange(4).reshape(2,2)
In [15]: np.append(a,b,axis = 0)
Out[15]:
array([[0, 1],
[0, 1],
[2, 3]])
concatenate
concatenate((a1, a2, ...), axis=0, out=None)
其中,a1
、a2
等要级联的数组必须是有相同形状的,默认是假设这些数组是三维的,所以如果在轴axis=0
上进行级联,那么a1
、a2
等数组的形状必须是(x, _, _)
。其中只能x
位置可以为不相同的正整数外,其他位置必须一致。
# 默认的是axis = 0
In [13]: a = np.arange(2).reshape(1,2)
In [14]: b = np.arange(4).reshape(2,2)
In [18]: np.concatenate((a,b))
Out[18]:
array([[0, 1],
[0, 1],
[2, 3]])
# 如果想在axis = 1上级联,则是不可以的因为除了
# axis = 1外,形状并不相同。
In [19]: np.concatenate((a,b),axis = 1)
ValueError: all the input array dimensions except for
the concatenation axis must match exactly
# 因此我们将a转置一下就好了。
In [20]: np.concatenate((a.T,b), axis = 1)
Out[20]:
array([[0, 0, 1],
[1, 2, 3]])
当axis
为None
时,合并所有数组元素。
In [21]: np.concatenate((a.T,b),axis = None)
Out[21]: array([0, 1, 0, 1, 2, 3])
值得注意的是,如果你传入的是MaskedArrays
数组,那么使用np.concatenate
是不会保存mask
的。你需要使用np.ma.concatenate
。
In [23]: mask_a
Out[23]:
masked_array(
data=[0, 1, 2, 3, --],
mask=[False, False, False, False, True],
fill_value=2)
In [24]: mask_b
Out[24]:
masked_array(
data=[--, 6, 7, 8, 9],
mask=[True, False, False, False, False],
fill_value=5)
# 使用np.concatenate无法保存mask
In [25]: np.concatenate((mask_a,mask_b))
Out[25]:
masked_array(
data=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
mask=False,
fill_value=999999)
# 使用np.ma.concatenate可以保存mask 但依旧保存不了填充值
In [26]: np.ma.concatenate((mask_a,mask_b))
Out[26]:
masked_array(
data=[0, 1, 2, 3, --, --, 6, 7, 8, 9],
mask=[False, False, False, False, True, True, False, False, False, False],
fill_value=999999)
stack
np.stack(arrays, axis=0, out=None)
沿新轴连接一系列数组。这里的每个数组必须要有相同的形状(沿轴)。axis
指定了新轴的位置。例如,a
和b
的形状都是(3,)。那么a
和b
堆叠后的结果就只能为沿axis=0
得到形状(2,3)或者沿axis=1
得到形状(3,2)这两种情况。
In [8]: a = np.arange(3)
In [9]: b = np.arange(3,6)
In [11]: np.stack((a,b),axis = 0)
Out[11]:
array([[0, 1, 2],
[3, 4, 5]])
In [12]: np.stack((a,b),axis = 1)
Out[12]:
array([[0, 3],
[1, 4],
[2, 5]])
再举一个例子,如果a
和b
是一个形状为(4,3)的数组,那么堆叠起来就有axis=0
,axis=1
,axis=2
分别对应形状(2,4,3),(4,2,3),(4,3,2)这三种。
In [13]: a = np.arange(12).reshape(4,3)
In [14]: b = np.arange(1,13).reshape(4,3)
In [15]: np.stack([a,b],axis = 0).shape
Out[15]: (2, 4, 3)
In [16]: np.stack([a,b],axis = 1).shape
Out[16]: (4, 2, 3)
In [17]: np.stack([a,b],axis = 2).shape
Out[17]: (4, 3, 2)
block
np.block(arrays)
函数block
就是将数组按块排版。就像下图所示的这样,对于矩阵
,我们可以通过四小块构成:
。
In [4]: a = np.arange(4).reshape(2,2)
In [5]: b = np.arange(6).reshape(2,3)
In [6]: c = np.arange(2).reshape(2,1)S
In [7]: d = np.arange(8).reshape(2,4)
In [8]: np.block([[a,b],[c,d]])
Out[8]:
array([[0, 1, 0, 1, 2],
[2, 3, 3, 4, 5],
[0, 0, 1, 2, 3],
[1, 4, 5, 6, 7]])
hstack、vstack、dstack
hstack
np.hstack(tup)
hstack
方法等价于concatenate
方法沿着axis=1
级联(1-D数组沿axis=0
)。
- 1-D
通俗理解,hstack
的意思是horizontal stack
即水平堆叠。假设对于两个形状分别为(3,)和(2,)的1-D数组,因此我们只需要在水平轴上拼接即可。得到一个形状为(5,)的数组。
In [3]: a = np.arange(3)
In [4]: b = np.arange(2)
In [5]: np.hstack((a,b))
Out[5]: array([0, 1, 2, 0, 1])
- 2-D及以上
现在,让我们在1-D的基础上再加一维,假设对于两个形状分别为(2,3)和(4,5)的2-D数组进行水平堆叠是没有办法堆叠出一个规则数组的。我们令a
,b
分别是形状为(2,2),(2,3)的数组,这样a
在水平上的两形状为(2,)的元素就可以和b
上的两个(3,)分别进行水平堆叠。
In [33]: a = np.arange(4).reshape(2,2)
In [34]: b = np.arange(6).reshape(2,3)
In [35]: np.hstack((a,b))
Out[35]:
array([[0, 1, 0, 1, 2],
[2, 3, 3, 4, 5]])
如果在2-D以上叠加时,其实和2-D并无区别。我们可以把更高维度抽象为一个元素,只要这个元素的形状相同就能够使得其在水平上堆叠。总的来说在更高维度上水平堆叠时,仅需保持除axis=1
轴外形状相同即可。
In [5]: b = np.arange(24).reshape(2,3,4)
In [6]: a = np.arange(16).reshape(2,2,4)
In [7]: np.hstack((a,b))
Out[7]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
vstack
np.vstack(tup)
vstack
方法等价于concatenate
方法沿着axis=0
级联。
- 1-D
通俗理解,vstack
的意思是vertically stack
即垂直堆叠。假设对于两个形状分别为(3,)和(2,)的1-D数组,我们想要垂直堆叠是做不到的。
因此只有形状相同的情况下,两个数组才能垂直堆叠在一起。就像下图中的a
,b
在np.vasack((a,b))
后就得到下右图所示现状为(2,3)的数组。
In [9]: a = np.arange(3)
In [10]: b = np.arange(3)
In [11]: np.vstack((a,b))
Out[11]:
array([[0, 1, 2],
[0, 1, 2]])
- 2-D及以上
在垂直堆叠时,可对比hstack
水平堆叠。我们可以将更高维度就行抽象,除axis=0
外,只要高层保持形状相同便可以进行堆叠。
# 对于二维
In [4]: a = np.arange(6).reshape(2,3)
In [5]: b = np.arange(9).reshape(3,3)
In [6]: np.vstack((a,b))
Out[6]:
array([[0, 1, 2],
[3, 4, 5],
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
# 对于三维
In [7]: b = np.arange(9).reshape(3,3,1)
In [8]: a = np.arange(6).reshape(2,3,1)
In [9]: np.vstack((a,b))
Out[9]:
array([[[0],
[1],
[2]],
[[3],
[4],
[5]],
[[0],
[1],
[2]],
[[3],
[4],
[5]],
[[6],
[7],
[8]]])
dstack
np.dstack(tup)
dstack
就是depth stack
,是沿着axis=2
进行堆叠的。
对于1-D形状为(M,)
的数组,会被重塑为(1,M,1)
的形状,来进行深度堆叠,对于2-D形状为(M.N)
的数组则会被重塑为(M,N,1)
的形状,来进行深度堆叠。
# 对于一维
In [14]: a = np.arange(3)
In [15]: b = np.arange(3)
In [16]: np.dstack((a,b))
Out[16]:
array([[[0, 0],
[1, 1],
[2, 2]]])
# 对于二维
In [18]: b = np.arange(6).reshape(2,3)
In [19]: a = np.arange(6).reshape(2,3)
In [20]: np.dstack((a,b))
Out[20]:
array([[[0, 0],
[1, 1],
[2, 2]],
[[3, 3],
[4, 4],
[5, 5]]])
总结
这三个函数对三维的阵列是最有意义的。例如,对于具有高度(第一轴),宽度(第二轴)和深度(第三轴)的数据。我们只需要记住vstack
、hstack
、dstack
是分别对第一、二、三轴进行操作。
读者如果处理多维数据,建议使用函数concatenate
,stack
和block
提供的更常规的堆叠和串联操作。
拆分
方法 | 含义 |
---|---|
split | 将一个数组拆分为多个子数组。 |
array_split | 将一个数组拆分为大小相等或近似相等的多个子数组。 |
hsplit | 水平(按列)将数组拆分为多个子数组。 |
vsplit | 垂直(逐行)将数组拆分为多个子数组。 |
dsplit | 沿第3轴(深度)将数组拆分为多个子数组。 |
split
np.split(ary, indices_or_sections, axis=0)
如果indices_or_sections
是整型N
,则数组arr
会被切分成N
整份。如果不够切分则报错。
In [5]: a = np.arange(8)
# 切割成两份,够切
In [6]: np.split(a,2)
Out[6]: [array([0, 1, 2, 3]), array([4, 5, 6, 7])]
# 切割成三份,不够切 报错
In [7]: np.split(a,3)
ValueError: array split does not result in an equal division
如果indices_or_sections
是1-D数组,则会根据数组段来进行切分,举个例子;如果indices_or_sections
的值为[2,5],则会将arr
分为arr[:2]
、arr[2:5]
、arr[5:]
三个部分。当超出数组索引范围时,则会以空数组替代。
In [9]: a = np.arange(10)
# 未超出数组索引范围
In [10]: np.split(a,[2,5])
Out[10]: [array([0, 1]), array([2, 3, 4]), array([5, 6, 7, 8, 9])]
# 超出数组索引范围
In [13]: np.split(a,[2,5,10])
Out[13]:
[array([0, 1]),
array([2, 3, 4]),
array([5, 6, 7, 8, 9]),
array([], dtype=int32)]
array_split
np.array_split(ary, indices_or_sections, axis=0)
与split
不同的是,array_split
的indices_or_sections
参数只能为整型,且不够切分时N
等份时,最后一块则以len(arr)%N
保留,它的并无差别。
# 一维
In [4]: a = np.arange(8)
In [5]: np.array_split(a,3)
Out[5]: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7])]
#二维
In [8]: b = np.arange(8).reshape(2,4)
In [9]: np.array_split(b,2,axis = 1)
Out[9]:
[array([[0, 1],
[4, 5]]),
array([[2, 3],
[6, 7]])]
hsplit、vsplit、dsplit
- hsplit
np.hsplit(ary, indices_or_sections)
hsplit
是沿着axis=1
进行切分。indices_or_sections
详细切分使用过程与split
相似。
In [24]: a = np.arange(12).reshape(2,6)
# 够切,则切
In [25]: np.hsplit(a,3)
Out[25]:
[array([[0, 1],
[6, 7]]), array([[2, 3],
[8, 9]]), array([[ 4, 5],
[10, 11]])]
# 不够,则报错
In [26]: np.hsplit(a,4)
ValueError: array split does not result in an equal division
# 按数组切分
In [28]: np.hsplit(a,[3,5])
Out[28]:
[array([[0, 1, 2],
[6, 7, 8]]),
array([[ 3, 4],
[ 9, 10]]),
array([[ 5],
[11]])]
- vsplit
与hsplit
类似,这里不过多赘述。
In [29]: a = np.arange(12).reshape(2,6)
# 够切,则切
In [30]: np.vsplit(a,2)
Out[30]: [array([[0, 1, 2, 3, 4, 5]]), array([[ 6, 7, 8, 9, 10, 11]])]
# 不够,则报错
In [31]: np.vsplit(a,3)
ValueError: array split does not result in an equal division
# 按数组切分
In [32]: np.vsplit(a,[0,1])
Out[32]:
[array([], shape=(0, 6), dtype=int32),
array([[0, 1, 2, 3, 4, 5]]),
array([[ 6, 7, 8, 9, 10, 11]])]
- dsplit
与hsplit
类似,这里不过多赘述。
In [37]: a = np.arange(20).reshape(2,2,6)
# 够切,则切
In [38]: np.dsplit(a,2)
Out[38]:
[array([[[ 0, 1, 2],
[ 6, 7, 8]],
[[12, 13, 14],
[18, 19, 20]]]),
array([[[ 3, 4, 5],
[ 9, 10, 11]],
[[15, 16, 17],
[21, 22, 23]]])]
# 不够,则报错
In [39]: np.dsplit(a,4)
ValueError: array split does not result in an equal division
# 按数组切分
In [40]: np.dsplit(a,[1,2])
Out[40]:
[array([[[ 0],
[ 6]],
[[12],
[18]]]),
array([[[ 1],
[ 7]],
[[13],
[19]]]),
array([[[ 2, 3, 4, 5],
[ 8, 9, 10, 11]],
[[14, 15, 16, 17],
[20, 21, 22, 23]]])]