好奇的numpy高级索引选择案例

时间:2017-10-02 07:02:30

标签: python arrays numpy

这是一个Python程序,它使用高级索引以三种略微不同的方式对3D数组进行切片,以得到相同的结果。 a和b显示相同的预期结果。但是,c显示错误消息" IndexError:形状不匹配:索引数组不能与形状(3,)(2,)(1,)和#34;一起广播。 a,b和c之间的唯一区别是选择第二个指数范围的方式略有不同。为什么c出错:

import numpy as np

y = np.arange(0,18)
y1 = y.reshape((3,2,3))

print("y1 is \n{}\n".format(y1))

#a is ok
a = y1[[0,1,2],:,[False,False,True]]
print("a is \n{}\n".format(a))

#b is ok, same as a
b = y1[[0,1,2],0:2,[False,False,True]]
print("b is \n{}\n".format(b))

#below errors out
c = y1[[0,1,2],[0,1],[False,False,True]]
print("c is \n{}\n".format(c))

2 个答案:

答案 0 :(得分:0)

使用False作为索引0而使用True作为索引1有点令人困惑。

a = y1[[0,1,2],:,[False,False,True]]

或更好

a = y1[[0,1,2],:,[0,0,1]]

意味着,将每个列表的第一个元素作为索引,然后是第二个元素,......

a = [y1[0, :, 0], y1[1, :, 0], y1[2, :, 1]]

c的情况下,中间列表是短的,第三个元素缺失。

另一个例子,要说清楚

d = y1[[0,2,0],[0,1,0],[2,2,1]]

d = [y1[0, 0, 2], y1[2, 1, 2], y1[0, 0, 1]]

答案 1 :(得分:0)

这里的问题是:

  • 布尔索引的工作原理
  • 索引列表(数组)如何相互广播
  • 混合高级/基本索引的工作原理。
user_score = 0
simon_pattern = 'RRGBRYYBGY'
user_pattern  = 'RRGBBRYBGY'

for i in range(len(user_pattern)):
    if user_pattern[i] is simon_pattern[i]:
       user_score += 1
    else:
        break

print('User score:', user_score)

所以前两个产生一个(3,2)结果,最后一个产生错误。请注意,最后一个已将In [286]: y1 = np.arange(18).reshape(3,2,3) In [287]: y1 Out[287]: array([[[ 0, 1, 2], [ 3, 4, 5]], [[ 6, 7, 8], [ 9, 10, 11]], [[12, 13, 14], [15, 16, 17]]]) In [288]: y1[[0,1,2],:,[False, False, True]] Out[288]: array([[ 2, 5], [ 8, 11], [14, 17]]) In [289]: y1[[0,1,2],0:2,[False, False, True]] Out[289]: array([[ 2, 5], [ 8, 11], [14, 17]]) In [290]: y1[[0,1,2],[0,1],[False, False, True]] .... IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,) (1,) 转换为(1,)索引数组。

第一个与这个更简单的索引相同:

[False,False,True]

如果我使用布尔值,那就像我使用In [294]: y1[:,:,2] Out[294]: array([[ 2, 5], [ 8, 11], [14, 17]]) 一样:

y1[:,:,[2]]]

A(3,2,1)数组。

In [291]: y1[:,:,[False,False,True]] Out[291]: array([[[ 2], [ 5]], [[ 8], [11]], [[14], [17]]]) 生成相同的内容,但使用高级索引。布尔列表以相同的方式工作。 y1[np.ix_([0,1,2], [0,1], [2])]重塑3个数组,以便它们可以相互广播

ix_

这会创建一个(3,1,1),(1,2,1)和(1,1,1)广播到(3,2,1)。

In [299]: np.ix_([0,1,2],[0,1],[2]) Out[299]: (array([[[0]], [[1]], [[2]]]), array([[[0], [1]]]), array([[[2]]])) 也使用广播,a(3,)和(1,)生成(3,)。 (2,)中间维度被添加到最后。这是混合基本/高级索引的示例。在某些情况下,这是违反直觉的。例如,y1[[0,1,2], :, [2]]产生(3,2),而用户通常期望(2,3)。

Python multi-dimensional notation transpose automatically

布尔索引与0/1索引不同。

y1[[2], :, [0,1,2]]

选择In [297]: y1[[0,1,2], :, [0,0,1]] Out[297]: array([[ 0, 3], [ 6, 9], [13, 16]]) y1[0,:,0]y1[1,:,0]。它将2个列表的元素配对。它用(3,)广播一个(3,)。最后再添加中间切片。

请注意,如果布尔掩码为y1[2,:,1],则可能会出现问题,这相当于[True, False, True],大小为[0,2]索引。这不会与(2,)一起广播。

(3,)

使用In [307]: y1[[0,1,2],:,[True, False, True]] IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,) y1[[[0],[1],[2]],:,[True, False, True]]结果测试您的理解,以及 (3,2,2) y1[[[0],[1],[2]],[0,1],[True, False, True]]