开始

python科学计算_numpy_广播与下标

多维数组下标

多维数组的下标是用元组来实现每一个维度的,如果元组的长度比维度大则会出错,如果小,则默认元组后面补 : 表示全部访问;

如果一个下标不是元组,则先转换为元组,在转换过程中,列表和数组的转换有所不同。

一个列表会被转换成各个元素组成的元组,然后进行访问(此时如果不全为整数的话,则不会共享存储区域,因为无法通过改变步长来保持存储结构不变);如: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)

posted @ 2015-08-16 23:42  Lyon2014  阅读(589)  评论(0编辑  收藏  举报