#### 一、Numpy

##### 1.1 轴、维度及秩
###### 1.1.1 轴

numpy数组中的轴不太容易理解，但是却非常重要。官方定义为：轴即维度（In Numpy dimensions are called axes.）。

>>>arr1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> arr1
array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

>>> arr1.sum(axis=0)
array([12, 15, 18])
>>> arr1.sum(axis=1)
array([ 6, 15, 24])

>>> arr = np.array([[[0, 1, 2, 3], [4, 5, 6, 7]], [[8, 9, 10, 11], [12, 13, 14, 15]]])
>>> arr
array([[[ 0,  1,  2,  3],
[ 4,  5,  6,  7]],

[[ 8,  9, 10, 11],
[12, 13, 14, 15]]])

A = [0, 1, 2, 3]
B = [4, 5, 6, 7]
C = [ 8,  9, 10, 11]
D = [12, 13, 14, 15]
arr = [[A, B],
[C, D]]

# arr.sum(axis=0) = [A + C, B + D]
# A + C = [0+8, 1+9, 2+10, 3+11] = [8, 10, 12, 14]
# B + D = [4+12, 5+13, 6+14, 7+15] = [16, 18, 20, 22]
>>> arr.sum(axis=0)
array([[ 8, 10, 12, 14],
[16, 18, 20, 22]])
# arr.sum(axis=1) = [A + B, C + D]
>>> arr.sum(axis=1)
array([[ 4,  6,  8, 10],
[20, 22, 24, 26]])

# sum(A) = [0 + 1 + 2 + 3] = [6]
>>> arr.sum(axis=2)
array([[ 6, 22],
[38, 54]])

>>> arr2 = np.arange(0, 32)
>>> arr2
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
>>> arr2.reshape(4,2,2,2)
array([[[[ 0,  1],
[ 2,  3]],

[[ 4,  5],
[ 6,  7]]],

[[[ 8,  9],
[10, 11]],

[[12, 13],
[14, 15]]],

[[[16, 17],
[18, 19]],

[[20, 21],
[22, 23]]],

[[[24, 25],
[26, 27]],

[[28, 29],
[30, 31]]]])

A = [[ 0,  1], [ 2,  3]]
B = [[ 4,  5], [ 6,  7]]
C = [[ 8,  9],  [10, 11]]
D = [[12, 13],  [14, 15]]
E = [[16, 17],  [18, 19]]
F = [[20, 21],  [22, 23]]
G = [[24, 25], [26, 27]]
H = [[28, 29], [30, 31]]
arr2 = [[A, B],
[C, D],
[E, F],
[G, H]]

>>> arr2.sum(axis=1)
array([[[ 4,  6],
[ 8, 10]],

[[20, 22],
[24, 26]],

[[36, 38],
[40, 42]],

[[52, 54],
[56, 58]]])

>>> arr2.sum(axis=2)
array([[[ 2,  4],
[10, 12]],

[[18, 20],
[26, 28]],

[[34, 36],
[42, 44]],

[[50, 52],
[58, 60]]])
>>> arr2.sum(axis=3)
array([[[ 1,  5],
[ 9, 13]],

[[17, 21],
[25, 29]],

[[33, 37],
[41, 45]],

[[49, 53],
[57, 61]]])

###### 1.1.2 维度

numpy数组中的维度(dimension)官方定义说是指轴的个数，通俗点将，就是你要取得这个数组里面的某个元素必须使用的索引的个数，比如有如下数组：

arr1 = np.array([[1,2], [7,5]])

##### 1.2 数组转置

###### 1.2.2 三维数组

>>> import numpy as np
>>> arr = np.arange(0,16)
>>> arr
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])
>>> arr = arr.reshape(2,2,4)
>>> arr
array([[[ 0,  1,  2,  3],
[ 4,  5,  6,  7]],

[[ 8,  9, 10, 11],
[12, 13, 14, 15]]])

arr.transpose((2, 0, 1))

transpose()函数接受的是一个由轴编号组成的有序元组，表示变换后的新数组的轴编号顺序。上述代码的含义就是：将原数组的轴2变换为新数组的轴0，原数组的轴0变换为新数组的轴1，原数组的轴0变换为新数组的轴1。

1. 定维度。根据变换前后各个轴轴向维度不变原理，可以确定变换后的数组形式；
2. 定内层。先确定最内层元素的形式；
3. 递归。确定内层元素后，由内向外，逐层确定元素形式及内容。

1. 定维度。变换前各个轴的维度（注意：这里的维度是指各个轴方向元素的个数，与数组的维度有所区别。）如下：

\begin{align*} \huge \lbrack \ \LARGE &\lbrack \ \lbrack \ \square \ , \ \square \rbrack \ , \ \lbrack \ \square \ , \ \square \rbrack \ \rbrack , \\ &\lbrack \ \lbrack \ \square \ , \ \square \rbrack \ , \ \lbrack \ \square \ , \ \square \rbrack \ \rbrack , \\ &\lbrack \ \lbrack \ \square \ , \ \square \rbrack \ , \ \lbrack \ \square \ , \ \square \rbrack \ \rbrack , \\ &\lbrack \ \lbrack \ \square \ , \ \square \rbrack \ , \ \lbrack \ \square \ , \ \square \rbrack \ \rbrack \huge \ \rbrack \end{align*}

2. 定内层。对于内层数组而言，是一个1 × 2的矩阵，变换后的新数组的轴2（即最内层数组的行方向）是原来的数组的轴1（即最外层数组的列方向），原数组的列方向数字依次为0,1,2,3⟶，所以变换后最内层数组的行方向元素依次为：

3. 递归。内层数组首元素确定后，我们还需要根据外层数组的行列才能完全确定变换后的数组。上可知，变换后的数组的列方向是原数组的行方向，于是得到列首元素：

>>> arr.transpose(2,0,1)
array([[[ 0,  4],
[ 8, 12]],

[[ 1,  5],
[ 9, 13]],

[[ 2,  6],
[10, 14]],

[[ 3,  7],
[11, 15]]])

##### 1.3 轴对换

ndarray还提供了轴对换方法，名为swapaxes，它接受一对轴编号，然后将给定的两个轴的数据进行对换，它的作用于数组转置相同，只不过它每一次只能完成两个轴的交换，而transpose方法则可以是3个及以上，swapaxes用法如下：

>>> arr.swapaxes(1,2)
array([[[ 0,  4],
[ 1,  5],
[ 2,  6],
[ 3,  7]],

[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])