改变数组的形状#
一个数组的形状是由每个轴的元素数量决定的。可以通过多种方式改变数组的形状,以下介绍常用的函数或方法。
最常用的形状操作是获得一个数组(一般是二维数组)的转置,这种操作可通过 numpy.transpose 函数、ndarray.transpose 方法和 ndarray.T 特征属性实现,这三者是等同的。
import numpy as np
b = np.array([[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23],
[30, 31, 32, 33],
[40, 41, 42, 43]])
print(np.transpose(b))
print(b.T)
print(b.transpose())
# 以上三行均打印:
# [[ 0 10 20 30 40]
# [ 1 11 21 31 41]
# [ 2 12 22 32 42]
# [ 3 13 23 33 43]]
第二个常用的形状操作是 numpy.ravel 函数及其等价的 ndarray.ravel 方法,该操作返回一个连续的一维扁平数组,其中包含输入数组的所有元素,返回数组的元素类型与输入数组相同。
第三个常用的形状操作是 numpy.reshape 函数及其等价的 ndarray.reshape 方法,该造作返回一个与给定数组具有相同数据的数组,其形状根据输入参数 newshape 确定。新形状 newshape 必须与原来的形状相容(元素个数相同),如果某个维度所给定的值为 -1,则其他维度数将会被自动计算。
numpy.ravel(a, order='C')
numpy.reshape(a, newshape, order='C')
这两种操作中默认值为 'C' 的 order 表示采用 C 语言风格的以行为主的元素索引顺序;另外还有其他 order,请自行查看文档。这两种操作都不改变原来的数组。
import numpy as np
a = np.array([[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23]])
print(a.ravel()) # [ 0 1 2 3 10 11 12 13 20 21 22 23]
print(a.reshape(2, 6))
print(np.reshape(a, (2, 6)))
print(a.reshape(2, -1))
print(a.reshape(-1, 6))
# 以上 4 行代码均打印:
# [[ 0 1 2 3 10 11]
# [12 13 20 21 22 23]]
最后介绍 numpy.resize 函数和ndarray.resize 方法。
numpy.resize 函数返回一个具有指定形状的新数组。不同于 reshape,resize 中给定的形状可以和原数组不兼容(元素数比原数组小或大),如果新给定的形状大于原数组,则新数组将以原数组的内容重复进行填充。该函数不影响原数组。
ndarray.resize 方法并不与 numpy.resize 等价,该方法将直接改变数组的形状和大小(在需要时重新为数组分配内存空间),并且当新形状大于原形状时,多出来的元素将以 0 填充(不是用原数组的内容重复填充)。
numpy.resize(a, new_shape)
ndarray.resize(new_shape, refcheck=True)
import numpy as np
a = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
print(np.resize(a, (3, 2)))
# [[0 1]
# [2 3]
# [4 5]]
print(np.resize(a, (3, 5)))
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 0 1 2]]
# 这时 a 并没有改变
a.resize((3, 2))
print(a)
# [[0 1]
# [2 3]
# [4 5]]
a.resize(3, 4)
print(a)
# [[0 1 2 3]
# [4 5 0 0]
# [0 0 0 0]]
将不同数组堆叠在一起#
多个数组可以沿不同的轴堆叠在一起。常用的函数包括:
concatenate:沿现有轴连接一系列数组。stack:沿一个新的轴连接一系列数组。block:从嵌套的块列表中组装一个n 维数组。hstack:在水平方向(按列)堆叠数组。vstack:在垂直方向(按行)堆叠数组。dstack:按深度顺序堆叠数组(沿第三个轴)。column_stack:将一维数组作为列堆叠成二维数组。
以下是使用 hstack 和 vstack 函数进行数组堆叠的示例:
import numpy as np
rng = np.random.default_rng()
a = np.floor(10 * rng.random((2, 2)))
print(a)
# [[4. 9.]
# [2. 4.]]
b = np.floor(10 * rng.random((2, 2)))
print(b)
# [[5. 6.]
# [0. 8.]]
print(np.vstack((a, b)))
# [[4. 9.]
# [2. 4.]
# [5. 6.]
# [0. 8.]]
print(np.hstack((a, b)))
# [[4. 9. 5. 6.]
# [2. 4. 0. 8.]]
将一个数组拆分成几个较小的数组#
与堆叠相反,也可拆分数组。常用的函数包括:
split:将一个数组拆分成多个相同大小的子数组,这些子数组都是原数组的视图。当不能等分时,将触发异常。array_split:与split相似,但不能等分时不会触发异常。hsplit:将一个数组水平(按列)拆分成多个相同大小的子数组。vsplit:将一个数组水平(按行)拆分成多个相同大小的子数组。dsplit:将一个数组沿第三轴(深度)拆分成多个相同大小的子数组。
以下是使用 hsplit 函数进行数组拆分的示例:
import numpy as np
rng = np.random.default_rng()
a = np.floor(10 * rng.random((2, 12)))
print(a)
# [[5. 2. 5. 2. 8. 4. 9. 4. 6. 3. 3. 0.]
# [6. 8. 0. 0. 9. 4. 4. 0. 0. 3. 9. 5.]]
print(np.hsplit(a, 3))
# [array([[5., 2., 5., 2.],
# [6., 8., 0., 0.]]), array([[8., 4., 9., 4.],
# [9., 4., 4., 0.]]), array([[6., 3., 3., 0.],
# [0., 3., 9., 5.]])]
print(np.hsplit(a, (3, 4)))
# [array([[5., 2., 5.],
# [6., 8., 0.]]), array([[2.],
# [0.]]), array([[8., 4., 9., 4., 6., 3., 3., 0.],
# [9., 4., 4., 0., 0., 3., 9., 5.]])]