1.3.2.4数组形状操作
1.3.2.4.1 扁平
In [147]:
a = np.array([[1, 2, 3], [4, 5, 6]])
a.ravel()
Out[147]:
array([1, 2, 3, 4, 5, 6])
In [148]:
a.T
Out[148]:
array([[1, 4],
[2, 5],
[3, 6]])
In [149]:
a.T.ravel()
Out[149]:
array([1, 4, 2, 5, 3, 6])
高维:后进先出。
1.3.2.4.2 重排
扁平的相反操作:
In [150]:
a.shape
Out[150]:
(2, 3)
In [152]:
b = a.ravel()
b = b.reshape((2, 3))
b
Out[152]:
array([[1, 2, 3],
[4, 5, 6]])
或者:
In [153]:
a.reshape((2, -1)) # 不确定的值(-1)将被推导
Out[153]:
array([[1, 2, 3],
[4, 5, 6]])
警告: ndarray.reshape
可以返回一个视图(参见 help(np.reshape)
), 也可以可以返回副本
In [155]:
b[0, 0] = 99
a
Out[155]:
array([[99, 2, 3],
[ 4, 5, 6]])
当心:重排也可以返回一个副本!:
In [156]:
a = np.zeros((3, 2))
b = a.T.reshape(3*2)
b[0] = 9
a
Out[156]:
array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.]])
要理解这个现象,你需要了解更多关于numpy数组内存设计的知识。
1.3.2.4.3 添加纬度
用 np.newaxis
对象进行索引可以为一个数组添加轴(在上面关于广播的部分你已经看到过了):
In [157]:
z = np.array([1, 2, 3])
z
Out[157]:
array([1, 2, 3])
In [158]:
z[:, np.newaxis]
Out[158]:
array([[1],
[2],
[3]])
In [159]:
z[np.newaxis, :]
Out[159]:
array([[1, 2, 3]])
1.3.2.4.4 纬度重组
In [160]:
a = np.arange(4*3*2).reshape(4, 3, 2)
a.shape
Out[160]:
(4, 3, 2)
In [161]:
a[0, 2, 1]
Out[161]:
5
In [163]:
b = a.transpose(1, 2, 0)
b.shape
Out[163]:
(3, 2, 4)
In [164]:
b[2, 1, 0]
Out[164]:
5
也是创建了一个视图:
In [165]:
b[2, 1, 0] = -1
a[0, 2, 1]
Out[165]:
-1
1.3.2.4.5 改变大小
可以用 ndarray.resize
改变数组的大小:
In [167]:
a = np.arange(4)
a.resize((8,))
a
Out[167]:
array([0, 1, 2, 3, 0, 0, 0, 0])
但是,它不能在其他地方引用:
In [168]:
b = a
a.resize((4,))
------------- ------------- ------------- ------------- -----------------------
ValueError Traceback (most recent call last)
<ipython-input-168-59edd3107605> in <module>()
1 b = a
----> 2 a.resize((4,))
ValueError: cannot resize an array that references or is referenced
by another array in this way. Use the resize function
练习:形状操作
- 看一下
reshape
的文档字符串,特别要注意其中关于副本和视图的内容。 - 用
flatten
来替换ravel
。有什么区别? (提示: 试一下哪个返回视图哪个返回副本) - 试一下用
transpose
来进行纬度变换。