NumPy数组变形
reshape()
函数
在 NumPy 中,要改变数组的形状 (也称重塑数组),可以使用 numpy.reshape() 函数。reshape() 函数允许你指定一个新的形状,然后返回一个拥有相同数据但具有新形状的数组。
下面介绍 numpy.reshape()
函数
numpy.reshape(a, newshape, order='c')
函数
参数说明
a 参数是要被重塑的数组,可以是一个数组对象,也可以是一个 Python 列表、元组等支持迭代的对象。
newshape 参数是新的形状,可以是一个整数元组或列表,也可以是一个整数序列。
order 参数表示重塑数组的元素在内存中存储的顺序,可以是 'C' (按行顺序存储) 或 'F' (按列顺序存储),默认值为 'C'。
常见用法
a. 改变数组的维度:可以将一个数组从一维改为二维、三维等。例如:
import numpy as np a = np.arange(12) # 创建一个长度为 12 的一维数组 b = np.reshape(a, (3, 4)) # 改变为 3 行 4 列的二维数组 c = np.reshape(a, (2, 3, 2)) # 改变为 2 个 3 行 2 列的三维数组
b. 展开数组:可以将一个多维数组展开为一维数组。例如:
import numpy as np a = np.array([[1, 2], [3, 4]]) b = np.reshape(a, -1) # 将二维数组展开为一维数组
c. 改变数组的顺序:可以改变数组在内存中的存储顺序。例如:
import numpy as np a = np.arange(6).reshape((2, 3)) # 创建一个 2 行 3 列的二维数组 b = np.reshape(a, (3, 2), order='F') # 按列顺序存储
注意
numpy.reshape()
函数并不会改变数组的数据类型和数据本身,只会改变其形状。如果改变后的形状与原数组的元素数量不一致,将会抛出 ValueError 异常。
一维数组 —> 行向量、列向量
一维数组 —> 行向量
行向量、列向量都是特殊矩阵。因此,行向量、列向量都是二维数组。也就是说,行向量是一行若干列的数组,形状为 1 × D。列向量是若干行一列的数组,形状为 n × 1。
下面是一维数组转换为行向量的例子:
import numpy as np
a = np.arange(-7, 7+1)
# [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]
b = np.reshape(a, (1, -1))
# [[-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]]
上面例子首先用 a = numpy.arange(-7, 7+1)
生成一个一维数组 a,这个数组有 15 个元素。利用 numpy.reshape(a, (1, -1))
,我们将 a 转化为形状为 (1, 15) 的二维数组,也称行向量,即 1 × 15 矩阵。
提示
注意,使用 -1 作为形状参数时,numpy.reshape() 会根据数组中的数据数量和其它指定的维数来自动计算该维度的大小。
一维数组 —> 列向量
与上将一维数组转化为行向量类型,我们只需要利用 numpy.reshape(a, (-1, 1))
,就可以把一维数组 numpy.arange(-7, 7+1)
转化为形状为 (15, 1) 的二维数组,也称列向量,即 15 × 1 矩阵。
一维数组 —> 二维数组
用 a = numpy.arange(-7, 7+1) 生成的数组有 15 个元素,可以被 3、5 整除,因此一维数组 a 可以写成 3 × 5 矩阵。下面我们可以分别按先行后列、先列后行两种形式重塑数组。
import numpy as np
a = np.arange(-7, 7+1)
# [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]
b = np.reshape(a, (3, -1))
# [[-7 -6 -5 -4 -3]
# [-2 -1 0 1 2]
# [ 3 4 5 6 7]]
c = np.reshape(a, (3, -1), order='F')
# [[-7 -4 -1 2 5]
# [-6 -3 0 3 6]
# [-5 -2 1 4 7]]
视图 VS 副本
本书前文特别提过,NumPy 中要特别注意视图 (view)、副本 (copy) 的区别。简单来说,视图和副本是 NumPy 中的两种不同的数组对象。
视图是指一个数组的不同视角或者不同形状的表现方式,视图和原始数组共享数据存储区,因此在对视图进行操作时,会影响原始数组的数据。视图可以通过数组的切片、转置、重塑等操作创建。
副本则是指对一个数组的完全复制,副本和原始数组不共享数据存储区,因此对副本进行操作不会影响原始数组。
注意
需要注意的是,使用 numpy.reshape() 仅仅改变了观察同一数组的视角,改变视图的时候也会同时改变原数组。
转置
一个 n × D 矩阵 A 转置得到 D × n 矩阵 B,整个过程相当于矩阵 A 绕主对角线镜 像。具体来说,矩阵 A 位于 (i, j) 的元素转置后的位置为 (j, i),即行列序号互换。矩阵 A 的转置 (the transpose of a matrix A) 记作 A^T。
注意
NumPy 中的 numpy.transpose() 方法和.T 属性都返回原始数组的转置,两者都返回原始数组的视图,而不是副本。
扁平化
扁平化可以理解为 numpy.reshape()
的 “逆操作”。完成扁平化的方法有很多,比如 array.ravel()
、array.reshape(-1)
、array.flatten()
。也可以使用 numpy.ravel()
、numpy.flatten()
这两个函数。
下面是使用例:
import numpy as np
a = np.arange(-7, 7+1)
b = np.reshape(a, (3, -1))
c = np.ravel(b)
# [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]
注意
ravel()
、reshape(-1)
返回的是原始数组的视图,而不是其副本。因此,如果修改新数组中的任何元素,原始数组也会受到影响。如果需要返回一个数组副本,可以使用 flatten()
函数。
其它操作
numpy.rot90()
numpy.rot90()
可以将一个数组逆时针旋转 90 度。默认情况下,这个函数会将数组的前两个维度 axes=(0, 1) 进行旋转。此外,还可以利用参数 k (正整数) 逆时针旋转 k × 90 度。默认 k = 1。
numpy.flip()
numpy.flip()
函数用于翻转数组中的元素,即将数组沿着一个或多个轴翻转。numpy.flip(A, axis=None)
中,A 是要进行翻转的数组,axis 指定要翻转的轴。如图 12所示,如果不指定 axis, 则默认将整个数组沿着所有的轴进行翻转。类似的函数还有 numpy.fliplr()
、numpy.flipud()
等。