NumPy快速入门——数组进阶操作
Posted serity
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NumPy快速入门——数组进阶操作相关的知识,希望对你有一定的参考价值。
目录
一、改变数组的形状
函数 | 作用 |
---|---|
np.reshape(a, newshape) | a是数组,newshape是整型元组;返回newshape形状的数组 |
np.ravel(a) | 展平成一维数组;等价于np.reshape(a, -1) |
np.flatten(a) | 效果和ravel一样,但更推荐使用flatten |
1.1 np.reshape()
A = np.arange(6).reshape((2, 3))
print(A)
# [[0 1 2]
# [3 4 5]]
事实上元组的括号可以省略,即我们可以更简洁地使用reshape:
A = np.arange(6).reshape(2, 3)
newshape 中的某一个分量可以为-1,reshape会根据其他分量自动推算:
A = np.arange(6).reshape(2, -1)
print(A)
# [[0 1 2]
# [3 4 5]]
若 newshape = -1,那么reshape会将其展平为一维数组:
A = np.arange(6).reshape(6).reshape(-1)
print(A)
# [0 1 2 3 4 5]
1.2 np.ravel()
A = np.arange(8).reshape(2, 2, 2).ravel()
print(A)
# [0 1 2 3 4 5 6 7]
1.3 np.flatten()
A = np.arange(8).reshape(2, 2, 2).flatten()
print(A)
# [0 1 2 3 4 5 6 7]
可以看出flatten的效果和ravel一样,那使用哪一个更好呢?
直接说答案:使用flatten更好,具体原因见博客。
二、(类)转置操作
函数 | 作用 |
---|---|
ndarray.T | 转置一个数组,即反转shape |
np.swapaxes(a, axis1, axis2) | 交换数组的两个轴 |
np.moveaxis(a, s, d) | s 和 d 是整数或整型列表;将索引为 s 的轴移动到索引 d 处 |
2.1 ndarray.T
A = np.arange(6).reshape(2, 3)
print(A)
print(A.T)
# [[0 1 2]
# [3 4 5]]
# [[0 3]
# [1 4]
# [2 5]]
但要注意,ndarray.T 无法转置一维数组:
A = np.arange(6)
print(A)
print(A.T)
# [0 1 2 3 4 5]
# [0 1 2 3 4 5]
那我们该如何转置一维数组呢?有以下几种方法:
方法一:先转换为二维数组
将 ndarray 变成二维数组再进行转置:
A = np.arange(4)
A = np.array([A])
print(A.T)
# [[0]
# [1]
# [2]
# [3]]
当然也可以使用 np.transpose(),它与 ndarray.T 等价:
A = np.arange(4)
print(np.transpose([A]))
# [[0]
# [1]
# [2]
# [3]]
方法二:使用reshape函数
A = np.arange(4)
A = A.reshape(len(A), -1) # 第二个参数改为1也可以
print(A)
# [[0]
# [1]
# [2]
# [3]]
方法三:使用newaxis
我们在本系列的第一篇文章中提到了 np.newaxis,这里我们将进一步讲解它的用法.
newaxis 的本质是 None:
print(np.newaxis == None)
# True
正如其名,将 newaxis 和 切片结合起来使用可以为数组添加一个新的维度(轴),它能将一维数组变为二维数组,将二维数组变为三维数组,也可以直接将一维数组变为三维数组等。
巧记: newaxis 位于哪一轴,则得到的结果沿该轴的长度就为1
可能不太好理解,这里举几个例子。假设 A 是一个长度为3的一维数组,则:
A[np.newaxis, :]
: newaxis位于第一个轴,则得到的结果是一个 1 × 3 1\\times 3 1×3 的数组。A[:, np.newaxis]
: newaxis位于第二个轴,则得到的结果是一个 3 × 1 3\\times1 3×1 的数组。A[:, np.newaxis, np.newaxis]
: newaxis位于第二个轴和第三个轴,则得到的结果是一个 3 × 1 × 1 3\\times1\\times1 3×1×1 的数组。
我们再举几个例子并结合shape方法来进一步说明 newaxis 的效果。
首先创建一个 3 × 4 3\\times4 3×4 的数组:
A = np.arange(12).reshape(3, 4)
print(A.shape)
# (3, 4)
然后使用 newaxis 添加新的轴:
print(A[:, :, np.newaxis].shape)
print(A[:, np.newaxis, :].shape)
print(A[np.newaxis, :, :].shape)
print(A[np.newaxis, np.newaxis, :, :].shape)
# (3, 4, 1)
# (3, 1, 4)
# (1, 3, 4)
# (1, 1, 3, 4)
看完这些例子,相信你对 newaxis 已经有了一个基本的认知,那如何转置一个维数组也不再是难事了。
因为转置后的一维数组一定是形如
a
×
1
a\\times 1
a×1 的形状,因此 newaxis 一定位于第二个轴,所以只需要 A[:, np.newaxis]
即可转置:
A = np.arange(4)
print(A[:, np.newaxis])
# [[0]
# [1]
# [2]
# [3]]
2.2 np.swapaxes()
A = np.zeros((3, 4, 5))
print(A.shape)
# (3, 4, 5)
print(np.swapaxes(A, 0, 1).shape)
print(np.swapaxes(A, 0, 2).shape)
print(np.swapaxes(A, 1, 2).shape)
# (4, 3, 5)
# (5, 4, 3)
# (3, 5, 4)
2.3 np.moveaxis()
s 和 d 都为整数时:
A = np.zeros((3, 4, 5))
print(np.moveaxis(A, 0, 2).shape)
print(np.moveaxis(A, 0, -1).shape)
print(np.moveaxis(A, -1, -2).shape)
# (4, 5, 3)
# (4, 5, 3)
# (3, 5, 4)
s 和 d 都为整型列表时:
A = np.zeros((3, 4, 5))
print(np.moveaxis(A, [0, 1], [1, 2]).shape)
print(np.moveaxis(A, [0, 1], [0, 2]).shape)
print(np.moveaxis(A, [1, 0], [0, 2]).shape)
# (5, 3, 4)
# (3, 5, 4)
# (4, 5, 3)
三、合并数组
函数 | 作用 |
---|---|
np.concatenate((a1, a2, …), axis=0) | a1, a2等是数组,axis控制连接的方向;用于将多个数组连接在一起,当axis为None时,会在连接之前压平将要连接的各个数组 |
np.stack(arrays, axis=0) | arrays是由数组组成的列表或元组;沿axis方向堆叠这些数组 |
np.block(arrays) | 将若干个数组组合在一起构成一个新数组;常用于构建分块矩阵 |
np.vstack((a1, a2, …)) | 垂直堆叠数组 |
np.hstack((a1, a2, …)) | 水平堆叠数组 |
3.1 np.concatenate()
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
print(np.concatenate((a, b), axis=0))
# [[1 2]
# [3 4]
# [5 6]]
print(np.concatenate((a, b.T), axis=1))
# [[1 2 5]
# [3 4 6]]
print(np.concatenate((a, b), axis=None))
# [1 2 3 4 5 6]
若要连接两个一维数组,只需要:
a = np.array([1, 2])
b = np.array([3, 4])
print(np.concatenate((a, b)))
# [1 2 3 4]
3.2 np.stack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.stack((a, b)))
# [[1 2 3]
# [4 5 6]]
print(np.stack((a, b), axis=1))
# [[1 4]
# [2 5]
# [3 6]]
arrays = [np.zeros((2, 3)) for _ in range(4)]
print(np.stack(arrays, axis=0).shape)
print(np.stack(arrays, axis=1).shape)
print(np.stack(arrays, axis=2).shape)
# (4, 2, 3)
# (2, 4, 3)
# (2, 3, 4)
注意到 axis=2
实际上就是最后一个轴,我们也可以用 axis=-1
来代替它,效果是一样的,其他轴也可以此类推:
print(np.stack(arrays, axis=-3).shape)
print(np.stack(arrays, axis=-2).shape)
print(np.stack(arrays, axis=-1).shape)
# (4, 2, 3)
# (2, 4, 3)
# (2, 3, 4)
3.3 np.block()
A = np.eye(2) * 2
B = np.eye(3) * 3
C = np.block([
[A, np.zeros((2, 3))],
[np.ones((3, 2)), B ]
])
print(C)
# [[2. 0. 0. 0. 0.]
# [0. 2. 0. 0. 0.]
# [1. 1. 3. 0. 0.]
# [1. 1. 0. 3. 0.]
# [1. 1. 0. 0. 3.]]
3.3 np.vstack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.vstack((a, b)))
# [[1 2 3]
# [4 5 6]]
更形象的解释:因为是垂直堆叠,所以把 B B B 放在 A A A 下面
A = [ 1 , 2 , 3 ] , B = [ 4 , 5 , 6 ] A=[1, 2, 3],\\quad B=[4,5,6] A=[1,2,3],B=[4,5,6]
a = np.array([[1], [2], [3]])
b = np.array([[4], [5], [6]])
print(np.vstack((a, b)))
# [[1]
# [2]
# [3]
# [4]
# [5]
# [6]]
同理把 B B B 放在 A A A 下面
A = [ 1 2 3 ] , B = [ 4 5 6 ] A=\\beginbmatrix 1 \\\\ 2\\\\ 3 \\\\ \\endbmatrix ,\\quad B=\\beginbmatrix 4 \\\\ 5\\\\ 6 \\\\ \\endbmatrix A=⎣⎡123⎦⎤,B=⎣⎡456⎦⎤
3.4 np.hstack()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.hstack((a, b)))
# [1 2 3 4 5 6]
更形象的解释:因为是水平堆叠,所以把 B B B 放在 A A A 右边
A = [ 1 , 2 , 3 ] , B = [ 4 , 5 , 6 ] A=[1, 2, 3],\\quad B=[4,5,6] A=[1,2,3],B=[4,5,6]
a = np.array([[1], [2], [3]])
b = np.array([[4], [5], [6]])
print(np.hstack((a, b)))
# [[1 4]
# [2 5]
# [3 6]]
同理把 B B B 放在 A A A 右边
A
=
[
1
以上是关于NumPy快速入门——数组进阶操作的主要内容,如果未能解决你的问题,请参考以下文章