这里的广播顺序是什么?

What is the broadcasting order here?

鉴于以下情况:

polygons = np.array([
       [[1, 0],
        [1, 1],
        [0, 0],
        [0, 1]],

       [[3, 2],
        [2, 2],
        [4, 4],
        [2, 3]]])

sort_idx = np.array([
       [2, 0, 1, 3],
       [1, 0, 2, 3]])

polygons[sort_idx]  #< The problematic part

预期输出为:

array([[[0, 0],
        [1, 0],
        [1, 1],
        [0, 1]],

       [[2, 2],
        [3, 2],
        [4, 4],
        [2, 3]]])

我希望 polygons[sort_idx] 到 return polygons 的“已排序”行,排序顺序由 sort_idx 中的值给出。 polygons[0][sorted_idx[0]](以及 [1] 的等价物)给出了正确的值,但是 运行 polygons[sort_idx] 提出:

IndexError: index 2 is out of bounds for axis 0 with size 2

我估计这个问题与我不了解该操作的广播方式有关,但我真的不知道要搜索什么或如何表达这个问题。我看到类似的问题建议使用 np.take()polygons[sort_idx,...],但两者都会引发相同的错误。我错过了什么?

使用np.take_along_axis:

np.take_along_axis(polygons, sort_idx[..., None], 1)
Out[]: 
array([[[0, 0],
        [1, 0],
        [1, 1],
        [0, 1]],

       [[2, 2],
        [3, 2],
        [4, 4],
        [2, 3]]])

take_along_axis 应该 'streamline' 索引我们必须做(并且仍然可以做):

In [233]: polygons[np.arange(2)[:,None], sort_idx]
Out[233]: 
array([[[0, 0],
        [1, 0],
        [1, 1],
        [0, 1]],

       [[2, 2],
        [3, 2],
        [4, 4],
        [2, 3]]])

第一个维度索引是(2,1),然后是第二个(2,4),在前2个维度一起广播到select(2,4)(最后一个维度不变).

sort_idx 的值适用于第 2 个轴,即 4 号轴。 polygons[sort_idx] 将它们应用于第一个大小为 2 的维度,因此出现错误。

对第一个维度使用切片 returns 值太多,一个块。我们想要更像对角线的东西:

In [235]: polygons[:, sort_idx,:].shape
Out[235]: (2, 2, 4, 2)

所以是的,这是一个 broadcasting 问题。当使用多个索引数组时,我们要考虑它们如何 broadcast 相互对抗。适用与运算符相同的规则。

In [236]: np.array([10,100])[:,None]* sort_idx
Out[236]: 
array([[ 20,   0,  10,  30],
       [100,   0, 200, 300]])