numpy提供了比常规的python序列更多的索引工具。正如我们前面看到的,除了按整数和切片索引之外,还可以使用数组进行索引
>>> a = np.arange(12)**2 array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121], dtype=int32) >>> i = np.array( [ 1,1,3,8,5 ] ) #一个包含索引数据的数组 >>> a[i] array([ 1, 1, 9, 64, 25]) >>> >>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] ) #一个二维索引数组 >>> a[j] # 最终结果和j的形状保持一致 array([[ 9, 16], [81, 49]])
当被索引的数组是多维数组时,将按照它的第一轴进行索引的,比如下面的例子:
>>> palette = np.array( [ [0,0,0], ... [255,0,0], ... [0,255,0], ... [0,0,255], ... [255,255,255] ] ) >>> image = np.array( [ [ 0, 1, 2, 0 ], ... [ 0, 3, 4, 0 ] ] ) >>> palette[image] array([[[ 0, 0, 0], [255, 0, 0], [ 0, 255, 0], [ 0, 0, 0]], [[ 0, 0, 0], [ 0, 0, 255], [255, 255, 255], [ 0, 0, 0]]])
我们这么理解:从image中每拿出一个元素,比如第一个元素0,然后去palette中找第0个行元素,也就是[0,0,0]
,将[0,0,0]
作为一个整体放在结果数组的第一个元素位置,如此类推,就得到了最终结果。
其实,还可以提供多个索引参数,如下所示:
>>> a = np.arange(12).reshape(3,4) >>> a array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> i = np.array( [ [0,1], ... [1,2] ] ) >>> j = np.array( [ [2,1], ... [3,3] ] ) >>> >>> a[i,j] array([[ 2, 5], [ 7, 11]]) >>> >>> a[i,2] array([[ 2, 6], [ 6, 10]]) >>> >>> a[:,j] array([[[ 2, 1], [ 3, 3]], [[ 6, 5], [ 7, 7]], [[10, 9], [11, 11]]])
上面的例子,其实就是从i中拿一个数,再从j的相同位置拿一个数,组成一个索引坐标,再去a中找元素。这有个前提,就是i和j必须是同构的。
我们还可以这么做:
>>> k = [i,j] >>> a[k] # 等同于a[i,j] array([[ 2, 5], [ 7, 11]])
但却不能这么做:
# 这个例子让人迷惑,所以不要自己给自己挖坑。简单的索引能达成目标,就不要玩花样。 >>> s = np.array( [i,j] ) >>> a[s] # 错误做法 Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: index (3) out of range (0<=index<=2) in dimension 0 >>> >>> a[tuple(s)] # 等同于a[i,j] array([[ 2, 5], [ 7, 11]])
比较有用的是下面的技巧:
# 用一个列表作为索引参数 >>> a = np.arange(5) >>> a array([0, 1, 2, 3, 4]) >>> a[[1,3,4]] = 0 >>> a array([0, 0, 2, 0, 0])
但是当索引出现重复的情况下,由最后的值决定最终结果:
>>> a = np.arange(5) >>> a[[0,0,2]]=[1,2,3] >>> a array([2, 1, 3, 3, 4])
看起来一切都很美好,但是当使用Python的+=这一类操作符的时候,结果却不那么美妙:
>>> a = np.arange(5) >>> a[[0,0,2]]+=1 >>> a array([1, 1, 3, 3, 4])
即使0在索引列表中出现两次,第0个元素也只增加一次。这是因为python要求“a+=1”等同于“a=a+1”。
多个索引参数那节注释有错 >>> a[i,j] # 等同于a[0][3],a[1][4]... 这里错了,应该是a[0][2],a[1][1],a[1][3],a[2][3]
感谢指出,已经修改。
多个或多维索引