多维数组的下标是用元组来实现每一个维度的,如果元组的长度比维度大则会出错,如果小,则默认元组后面补 : 表示全部访问;
如果一个下标不是元组,则先转换为元组,在转换过程中,列表和数组的转换有所不同。
一个列表会被转换成各个元素组成的元组,然后进行访问(此时如果不全为整数的话,则不会共享存储区域,因为无法通过改变步长来保持存储结构不变);如:lidx=[[0],[1],[2]];如果用lidx来访问一个数组,则会被转换成:([0],[1],[2]),即访问(0,1,2)上的元素;
一个数组会进行补 : 操作转成长度一致的元组,如三维数组a:
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, 32, 33, 34],
[35, 36, 37, 38, 39]],
[[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59]]])
如果使用一个数组来访问:aidx=np.array([[0],[1],[2]]):
array([[0],
[1],
[2]])
则会被补全为:(aidx,:,:),访问结果为:
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, 32, 33, 34],
[35, 36, 37, 38, 39]]],
[[[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59]]]])
结果的形状是访问下标数组的形状和原数组形状的组合:原数组形状为(3,4,5),下标数组形状为:(3,1);访问得到的数组形状为:(3,1,4,5);访问数组在0轴位置替代原数组形状;
相当于a(aidx,:,:),如果访问:a(:,aidx,:),则访问的形状应该为(3,3,1,5),即在1轴位置替代原数组形状;
再复习一下广播,详细规则见随笔:http://www.cnblogs.com/lyon2014/p/4696989.html
如上例的a数组,a.shape = (3,4,5),如果使用数组来访问,则会在对应的位置替代原数组的形状,如果下标中有多个数组,且形状不一致,则会进行广播,如:
i0 = np.array([[1,2,1],[0,1,0]]) ?, i0.shape=(2,3)
i1 = np.array([[[0]],[[1]]]), i1.shape=(2,1,1)
i2 = np.array([[[2,3,2]]]), i2.shape=(1,1,3)
按照广播的规则,i0的维数比最大维数3少,进行补1操作得到新的形状为:(1,2,3),再比较各个轴的长度:
1 2 3
2 1 1
1 1 3?
--------
2 2 3
最后结果的形状为(2,2,3),且满足第三条规则,可以进行计算;广播后的三个数组(记为:ind0,ind1,ind2)为:
ind0:
array([[[1, 2, 1],
[0, 1, 0]],
[[1, 2, 1],
[0, 1, 0]]])
ind1:
array([[[0, 0, 0],
[0, 0, 0]],
[[1, 1, 1],
[1, 1, 1]]])
ind2:
array([[[2, 3, 2],
[2, 3, 2]],
[[2, 3, 2],
[2, 3, 2]]])
此时,使用广播后的三个数组访问数组a(i0,i1,i2),得到的数组形状应该只与下标数组有关,即广播后的数组形状:(2,2,3);
如果a使用其中的两个数组访问:a(:,i0,i1),由于i0和i1广播后的形状为 (2,2,3),在1、2轴替换a数组的形状,最后得到的形状为:(3,2,2,3);
如果a使用其中两个数组访问,并且两个数组不连续:a(i0,:,i1),则第二轴会作为最后一维,即形状应该为广播后形状加上切片轴的形状:(2,2,3,4)
布尔数组作为下标时,相当于用nonzero()处理后的元组作为下标;
如:b2 = np.array([[True,False,True],[True,False,False]]) 作为下标,相当于:
np.nonzero(b2) =?(array([0, 0, 1]), array([0, 2, 0]))
a[b2] = a[np.nonzero(b2)] = a[ array([0, 0, 1]), array([0, 2, 0]), :?], 前两轴由于作为元组访问,最后得到的形状为(3,),最后访问到的形状为:(3,5)
原文:http://www.cnblogs.com/lyon2014/p/4735306.html