1, Ndarray 的转置
转置有三种方式,transpose
方法、T
属性以及swapaxes
方法。
1, .T,适用于一、二维数组
In [1]: import numpy as np
In [2]: arr = np.arange(20).reshape(4,5)#生成一个4行5列的数组
In [3]: arr
Out[3]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
In [4]: arr.T #求转置
Out[4]:
array([[ 0, 5, 10, 15],
[ 1, 6, 11, 16],
[ 2, 7, 12, 17],
[ 3, 8, 13, 18],
[ 4, 9, 14, 19]])
2. 对于高维数组,transpose需要用到一个由轴编号组成的元组,才能进行转置。
对多维数组来说,确定最底层的一个基本元素位置需要用到的索引个数即是维度。这句话的理解可以结合我索引和切片的那篇文章理解。
首先先定义一个简单的三维数组,可以知道shape为(2,3,4),对应0,1,2编号(可以理解为shape返回元祖(2,3,4)的索引)。
In [1]: import numpy as np
In [2]: arr=np.arange(24).reshape(2,3,4)
In [3]: arr
Out[3]:
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]]])
In [4]: arr.shape
Out[4]: (2, 3, 4) #说明这是一个2*3*4的数组(矩阵),返回的是一个元组,可以对元组进行索引,也就是0,1,2
3.引入三维坐标便于理解
坐标中的(0,1,2)(蓝色标的)三个维度就是shape返回元祖的索引编号,至于为什么垂直于底面的轴编号是0,可以联系二维数组进行推理。
如上图,将arr数组想象成三维空间,如长方体,0-11 12位数在长方体的顶面,12-23在长方体的底面。
- 当axis=0时,剩余的1,2维度组成了垂直于轴0的平面,这个平面上的数组有
[0,1,2,3
4,5,6,7
8,9,10,11] #数组0-1
[12,13,14,15
16,17,18,19
20,21,22,23] #数组0-2
- 当axis=1时,剩余的0,2维度组成了垂直于轴1的平面,这个平面上的数组有
[0,1, 2, 3
12,13,14,15] #数组1-1
[4,5,6,7
16,17,18,19] #数组1-2
[8,9,10,11
20,21,22,23] #数组1-3
- 当axis=2时,剩余的0,1维度组成了垂直于轴2的平面,这个平面上的数组有
[0, 4,8
12,16,20] #数组2-1
[1,5,9
13,17,21] #数组2-2
[2, 6,10
14,18,22] #数组2-3
[3,7,11
15,19,23] #数组2-4
形状 | 索引 |
2 | 0 |
3 | 1 |
4 | 2 |
transpose
参数的真正意义在于这个shape
元组的索引。多维元组它本身是如下的N维数组:
In [8]: arr.transpose(0,1,2)
Out[8]:
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]]])
那么它的转置就应该是arr.transpose(0,2,1)如下,(0->2,2->4,1->3 说明转置后是一个2个,4行,3 列的多维数组)
In [9]: arr.transpose(0,2,1)
Out[9]:
array([[[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]],
[[12, 16, 20],
[13, 17, 21],
[14, 18, 22],
[15, 19, 23]]])
他们是怎么计算得来的呢?
transpose之前3的索引是(0,0,3),8的索引是(0,2,0)。
现在transpose将原来3的索引顺序(0,0,3)改为了(0,3,0),8的索引为(0,0,2)
shape[0],shape[1],shape[2]原来分别表示矩阵3个维度的索引,tranpose之后根据transpoe的位置参数,索引的对应关系也发生变化,transpose(0,2,1)就表示原来的shape[1]和shape[2]对调,shape[0]不变,比如你举的例子里面原来8的索引为(0,2,0),transpose之后1和2对调,变成了(0,0,2),其他元素的位置也类似改变。
这也说明了,transpose
依赖于shape
。
4.根据以上三个维度,以下sum()函数实例就很好理解了。
A.轴编号为0时,数组0-1和数组0-2平面叠加
In [5]: np.sum(arr,axis=0)
Out[5]:
array([[12, 14, 16, 18],
[20, 22, 24, 26],
[28, 30, 32, 34]])
B.轴编号为1时,数组1-1和数组1-2和数组1-3平面叠加
In [6]: np.sum(arr,axis=1)
Out[6]:
array([[12, 15, 18, 21],
[48, 51, 54, 57]])
C.轴编号为2时,数组2-1和数组2-2、2-3、2-4平面叠加
In [7]: np.sum(arr,axis=2)
Out[7]:
array([[ 6, 22, 38],
[54, 70, 86]])
5.transpose()中三个轴编号的位置变化理解
transpose(a,b,c)其中a轴编号即为参考编号,垂直于a的平面即为所有平面,该平面上的数据再根据b,c相对于(0,1,2)的位置关系进行改变,下面以实例举例说明
A.transpose(0,1,2)对应的就是arr数组原形
In [8]: arr.transpose(0,1,2)
Out[8]:
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]]])
B.transpose(0,2,1),即以0为参考编号,数组0-1和0-2即为所求平面数组,但是2,1相对于(0,1,2)后面的轴编号进行了交换,所以数组0-1/0-2要以对角线进行.T转置(与二维数组的转置一样),所以结果如下。其余同理。
In [9]: arr.transpose(0,2,1)
Out[9]:
array([[[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]],
[[12, 16, 20],
[13, 17, 21],
[14, 18, 22],
[15, 19, 23]]])
C.以transpose(2,1,0)来验证以上操作。2为参考编号,数组2-1/2-2/2-3/2-4即为所求平面,其中(2,1,0)中1,0位置相较于(0,1,2)进行了互换,所以转置,结果如下。
In [10]: arr.transpose(2,1,0)
Out[10]:
array([[[ 0, 12],
[ 4, 16],
[ 8, 20]],
[[ 1, 13],
[ 5, 17],
[ 9, 21]],
[[ 2, 14],
[ 6, 18],
[10, 22]],
[[ 3, 15],
[ 7, 19],
[11, 23]]])
6.swapaxes(a,b)函数中两个轴编号理解
首先从词义上得知swap是“交换”的意思,swapaxes(a,b)函数则应该是a,b两个轴编号进行位置互换后数组的变化,这样原理和以上transpose相同了,下面实例验证
arr.swapaxes(0,1)=arr.swapaxes(1,0)=arr.transpose(1,0,2)
In [13]: arr.swapaxes(1,0)
Out[13]:
array([[[ 0, 1, 2, 3],
[12, 13, 14, 15]],
[[ 4, 5, 6, 7],
[16, 17, 18, 19]],
[[ 8, 9, 10, 11],
[20, 21, 22, 23]]])
-------------------------------------------
In [14]: arr.swapaxes(0,1)
Out[14]:
array([[[ 0, 1, 2, 3],
[12, 13, 14, 15]],
[[ 4, 5, 6, 7],
[16, 17, 18, 19]],
[[ 8, 9, 10, 11],
[20, 21, 22, 23]]])
------------------------------------------------
In [15]: arr.transpose(1,0,2)
Out[15]:
array([[[ 0, 1, 2, 3],
[12, 13, 14, 15]],
[[ 4, 5, 6, 7],
[16, 17, 18, 19]],
[[ 8, 9, 10, 11],
[20, 21, 22, 23]]])
另外举一个简单点的例子来理解swapaxes
In [67]: arr2 = np.arange(16).reshape(2,2,4)
In [68]: arr2
Out[68]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [69]: arr2.shape
Out[69]: (2, 2, 4)
In [70]: arr2.swapaxes(1,2)
Out[70]:
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
In [4]: arr2.swapaxes(1,0)#转置,对比transpose(1,0,2)
Out[4]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
In [59]: arr1 = np.arange(12).reshape(2,2,3)
In [60]: arr1
Out[60]:
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
2, cumsum 的计算过程详解
cumsum函数定义:
cumsum(a, axis=None, dtype=None, out=None)
a.cumsum(axis=None, dtype=None, out=None)
返回:沿着指定轴的元素累加和所组成的数组,其形状应与输入数组a一致
其中cumsum函数的参数:
a:数组
axis:轴索引,整型,若a为n维数组,则axis的取值范围为[0,n-1]
dtype:返回结果的数据类型,若不指定,则默认与a一致。
out:数据类型为数组。用来放置结果的替代输出数组,它必须具有与输出结果具有相同的形状和缓冲长度
1.对于一维数组而言:
import numpy as np
arr=np.array([1,2,3,4,5,6,7,8,9])
result=arr.cumsum() #此时axis只能取0,因此,axis=0可不写
#result: array([ 1, 3, 6, 10, 15, 21, 28, 36, 45], dtype=int32)
输出结果的数组result[i]的结果为sum(arr[:i+1])。
2.对于二维数组而言
import numpy as np
arr=np.array([[1,2,3],[4,5,6],[7,8,9]])
#沿着axis=0轴计算
result1=arr.cumsum(0) #array([[ 1, 2, 3],[ 5, 7, 9],[12, 15, 18]], dtype=int32)
#沿着axis=1轴计算
result2=arr.cumsum(1) #array([[ 1, 3, 6],[ 4, 9, 15],[ 7, 15, 24]], dtype=int32)
#arr.cumsum()并不是arr.cumsum(0)和arr.cumsum(1)的并集,而是将arr重塑为一维数组后的,再计算cumsum()的结果
arr.cumsum()#array([ 1, 3, 6, 10, 15, 21, 28, 36, 45], dtype=int32)
Cumsum :计算轴向元素累加和,返回由中间结果组成的数组
重点就是返回值是“由中间结果组成的数组”
以下代码在python3.7版本运行成功!
下面看代码,定义一个2*2*3的数组,所以其shape是2,2,3,索引分别0,1,2
形状 | 索引 |
2 | 0 |
2 | 1 |
3 | 2 |
3.对于n维数组而言,以3 维举例:
arr=np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
result1=arr.cumsum(0) #array([[[ 1, 2],[ 3, 4]],[[ 6, 8],[10, 12]]], dtype=int32)
result2=arr.cumsum(1) #array([[[ 1, 2],[ 4, 6]],[[ 5, 6],[12, 14]]], dtype=int32)
result3=arr.cumsum(2) #array([[[ 1, 3],[ 3, 7]],[[ 5, 11],[ 7, 15]]], dtype=int32)
输出结果的数组result1[i][j][k]的结果为sum(arr[:i+1,j,k]);
输出结果的数组result2[i][j][k]的结果为sum(arr[i,:j+1,k]);
输出结果的数组result3[i][j][k]的结果为sum(arr[i,j,:k+1])。
n维数组(n>3)的以此类推。
3, tile函数定义:
tile(A, reps)
返回一个数组,该数组是通过复制A reps次获得。
tile参数说明:
A:输入数组
reps:一个元组,代表沿各个轴重复A的次数。ps:A的顺序并不是单纯的按照axis增大或减小的顺序。
代码示例:
#输入一维数组
a = np.array([0, 1, 2])
#沿axis=1方向上复制2次,默认#沿axis=0方向上复制1次
np.tile(a, 2) #array([0, 1, 2, 0, 1, 2])
#沿axis=0方向上复制2次,#沿axis=1方向上复制1次
np.tile(a, (2, 1)) # array([[0, 1, 2],[0, 1, 2]])
##沿axis=2方向上复制2次,沿axis=0方向上复制1次,沿axis=1方向上复制3次,
np.tile(a, (2, 1, 3)) #array([[[0, 1, 2, 0, 1, 2, 0, 1, 2]],[[0, 1, 2, 0, 1, 2, 0, 1, 2]]])
#输入二维数组
b = np.array([[1, 2], [3, 4]])
#沿axis=1方向上复制2次,默认#沿axis=0方向上复制1次
np.tile(b, 2) #array([[1, 2, 1, 2],[3, 4, 3, 4]])
#沿axis=0方向上复制2次,#沿axis=1方向上复制1次
np.tile(b, (2, 1)) #array([[1, 2],[3, 4],[1, 2],[3, 4]])