目录
2.1 shape(A_1,A_2,A_3,…A_n)的含义
一、引入
#数组变形,不仅仅是reshape
import numpy as np
list_0=np.arange(5)
list_1=list_0[:,np.newaxis]
list_2=list_0[np.newaxis,:]
print("list_0是\n",list_0)
print("list_1是\n",list_0[:,np.newaxis])
print("list_2是\n",list_0[np.newaxis,:])
'''list_1和list_2分别长什么样?'''
#np.newaxis的位置到底有什么意义
可以看出我们通过newaxis,对原有的一维数组进行了升维,但newaxis放置的位置决定了新数组的长相。本文将从这儿出发,从shape,和变形表达式深入浅出的呈现数组是如何被变形的。
二、理解角度
newaxis: 创建新的轴,运行起来就是再套一层,问题就在于,从哪开始往外套一层。
1、拆分
我们注意到 list_0[newaxis,:]的结果就是直接在原有一维数组的整体的外面加了一层 "[ ]"
我们把list_0[newaxis,:]拆分成两个步骤:1、先给数组创建新的轴(得到一个新的数组);2、再对新数组进行切片(" : "是切片符号)
运行起来就是在[0 1 2 3 4]的外面套了一层,然后对这个[ [0 1 2 3 4] ]进行一次切片,
[ [0 1 2 3 4] ] [:]>>>当然这样的切片并没有什么意义
但在 list_[:,newaxis]上发生了不同,我们注意到是一维数组中的每一个元素被套了一层
如果也要拆分,貌似我们只能将切片理解做一个按数组进行遍历的循环,然后每一次循环会提取一个元素出来,然后对这一个单个元素套一层,最终达成了新建一个轴的效果。但不要认为套了一层就是新建了一个轴,要整体层次多一层才算多了一个轴(维度),单一的套一层只是让这一部分的维度升到了更高的维度,只有所有的更低维的被升维之后,新的轴才算建立完成。
我们代入拆分的角度来看更高维度的数组
import numpy as np
b = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
b_1=b[np.newaxis,:2]
b_2=b[:2,np.newaxis]
print("b是:\n",b)
print("\n")
print('b_1是:\n',b_1)
print('\n')
print('b_2是:\n',b_2)
print('\n')
对于b_1,我们依然可以认为对于整个二维数组,在外层再套一层
对于b_2,我们可以认为在这个二维数组中,进行一个切片,对每一次切片得到的小个体,进行一次升维。
1.5、插播
对哪个维度进行切片操作与这个切片出现的位置无关,跟这是第几个切片有关。且切片都是根据原数组,对最外层切片,若在一个高维数组里只有一个 " : " 的切片,即对最高维进行切片,但对其他低维度也是有全切片的,只是书写上省略了! 在这个例子中,最外层包含了三个一维数组,那么" :2 ",就是对前两个一维数组进行切片。如果在出现一次切片,则将是对再内一层——一维数组中的4个元素进行一次切片。
不管newaxis在哪个位置,总是先做完所有的切片!再根据整个式子里newaxis的位置,进行轴的插入
2、shape
如果文字看起来有些拗口,我们从ndarray的shape属性的角度出发再理解newaxis的运行。
2.1 shape(A_1,A_2,A_3,…A_n)的含义
表示在一个n维数组中,有A_1个(n-1)维数组,而每个(n-1)维数组中,有A_2个(n-2)维数组……每个一维数组中有A_n个元素。
#数组变形,不仅仅是reshape
import numpy as np
list_0=np.arange(5)
list_1=list_0[:,np.newaxis]
list_2=list_0[np.newaxis,:]
print("list_0是\n",list_0)
print("list_1是\n",list_0[:,np.newaxis])
print("list_2是\n",list_0[np.newaxis,:])
'''list_1和list_2分别长什么样?'''
#np.newaxis的位置到底有什么意义
我们再来看最开始的这段代码, list_0的shape是(5,)
list_1的shape是(5,1),我们注意到这个1被放到的位置也就是右边标红的位置[ : , np.newaxis],然后从shape的含义来看,list_1的确是在一个二维数组中有五个一维数组,这五个一维数组里都只有一个元素。
list_2的shape是(1,5),这个1仍然也是和newaxis对应着被放置>>>[np.newaxis , : ],同样的在list_2这个二维数组中有一个一维数组,这一个一维数组中就有5个元素。
当然如果我们要去象征性的切一点片,比如[ :2 , np.newaxis],你可以把list_0[:2]看作一个新的list
然后对这个list [ : ,np.newaxis]
因为二维比较常用,所以代码中的list_1与list_2也可以分别看作是获取列向量(一列),和行向量(一行)
然后我们来看那个更高维的数组
import numpy as np
b = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
b_1=b[np.newaxis,:2]
b_2=b[:2,np.newaxis]
print("b是:\n",b)
print("\n")
print('b_1是:\n',b_1)
print('\n')
print('b_2是:\n',b_2)
print('\n')
同样的,b的shape是(3,4),也就是说在这一个二维数组中,有3个一维数组,每个一维数组中有4个元素。
对于b1,在变形表达式 [ np.newaxis , :2 ]中,他也会在下划线标红位置插入一个新的轴。
根据”插播“中的规则>>>先进行切片:这个":2"的切片还是针对原来那个(3,4)的数组进行,也就是你会得到一个shape为(2,4)的,然后由于np.newaxis在变形表达式的最左边,那我们就在shape的最左边插入1,即得到(1,2,4)的数组
之所以是最左边是因为变形表达式可以看作[ np.newaxis , :2 , : ],这个变形表达式就可以看作是新数组的shape的一个模板!
对于b2,在变形表达式[ :2 ,np.newaxis]中,他是这样插入的:
切片>>>得到(2,4)的数组,然后在最右边插入一条轴,同样插入最右边的原因是变形表达式可以写作[ : 2 , : , np.newaxis ],以这个模板你可以构想出新的数组会是什么样,他的每个维度是由原数组的哪个部分组成的
三、更高维的例子,更多的组合,按步骤搭建新数组的模板
import numpy as np
b = np.array([[[1,2,3,4],[5,6,7,8],[9,10,11,12]]])#shape是1,3,4
In[1]
print(b[:,np.newaxis,:2])
print("\n")
print(b[:,np.newaxis,:2].shape)
我们现在有一个三维数组,shape(1,3,4),变形表达式是[ : , np.newaxis, :2] 根据之前的铺垫
1、这个三维数组里面有一个二维数组,每个二维数组里有三个一维数组,每个一维数组里4个元素
2、对于这个三维数组,如果是切片或者索引我们在完全考虑的情况下都会有三个参数
比如索引:[0,1,3],比如切片[ :1, :1, :3],先前所说的”第几个切片,其实就和这个地方是对应的,没写全的默认是全取。我们注意变形表达式和比如里的黄色背景和蓝色背景那它其实是这样的一种对应方式。
那么我对于这个shape(1,3,4)进行的实际切片是[ : , :2 , : ],得到的是(1,2,4)
我们进一步看np.axis的位置,被放在了第一个和第二个切片的中间,那么你变形得到的新数组的shape一定将会是 ( 1,1,2,4 )标红的就是插入的位置,新轴被放到了shape里第一个值和第二个值的中间
如果你的变形表达式是[ : , :3, np.newaxis],np.axis被放在第二个切片的右边,那你新得到的数组的将会是(1,3,1,4),标红的是插入位置。(3就是shape里第二个值)————没写全的切片的省略方式是完全会被newaxis隔断——要么把所有切片写完了,最后的位置添加轴,否则没写完的切片都是在np.newaxis的位置之后!
因此你可以根据——np.newaxis在哪一层切片的前后,确定在新数组的shape中,新的轴该在的位置
四、理解变形后数据的意义,或者说弄懂你变形前的数据去了哪里
我们沿用三维数组的例子。从(1,3,4)到(1,2,4)到(1,1,2,4)数据都在哪。
由于例子的特殊性,三维里只有一个二维,没有什么太大的意义。
(1,3,4)>>(1,2,4),把二维数组中的前两行(每行四个数)提出来了,放到新的二维数组里,然后把新的二维数组放到一个新的三维数组里
(1,2,4)>>(1,1,2,4),把这个有两行的二维数组放到一个三维数组里,再把这个三维数组放到一个四位数组里
>>>这个二维数组里的行仍然是完整的。每一行没有被割裂成几个几个的,行与行也没有分离,所以说他没有什么太大的意义
来个大的
一个shape(4,8,12)的三维数组,内含4个二维数组,每个二维数组内含8个一维数组,每个一维数组内含12个元素。我们把四个二维数组看作是四个不同公司,八个一维数组看作是公司有的八个部门,一维数组中的十二个元素看作一个部门一年十二个月的业绩。
假如我想要一个数组,里面要装两年的数据,是前两个公司的后四个部门的夏季的部门业绩。
一个三维数组只能涵盖一年,所以我们要扩充时间的维度,要在最顶层上添加轴。
你的变形表达式应当是[np.newaxis , :2 , 4: , 5:8 ](当然这已不只是扩充了数组,你还需要添加一个新的三维数组,这样这个四维数组就能够存储时间维度的数据)
假如我想要一个数组里存储上半年和下半年,我可能会对一维数组的十二个月进行分批。
效果大概是:[ : , : , np.axis , :6 ] 和 [ : , : , np.axis , 6: ]