np.choose 广播后没有给出预期的结果

np.choose not giving desired result after broadcasting

我想从 suitCounts 中选取 maxsuit 中指定的第 n 个元素。我确实广播了 maxsuit 数组,所以我确实得到了结果,但不是想要的结果。对我在概念上做错的任何建议表示赞赏。我不明白 np.choose(self.maxsuit[:,:,None]-1, self.suitCounts) 的结果,这不是我要找的结果。

>>> self.maxsuit
Out[38]: 
array([[3, 3],
       [1, 1],
       [1, 1]], dtype=int64)

>>> self.maxsuit[:,:,None]-1
Out[33]: 
array([[[2],
        [2]],

       [[0],
        [0]],

       [[0],
        [0]]], dtype=int64)
>>> self.suitCounts
Out[34]: 
array([[[2, 1, 3, 0],
        [1, 0, 3, 0]],

       [[4, 1, 2, 0],
        [3, 0, 3, 0]],

       [[2, 2, 0, 0],
        [1, 1, 1, 0]]])
>>> np.choose(self.maxsuit[:,:,None]-1, self.suitCounts)
Out[35]: 
array([[[2, 2, 0, 0],
        [1, 1, 1, 0]],

       [[2, 1, 3, 0],
        [1, 0, 3, 0]],

       [[2, 1, 3, 0],
        [1, 0, 3, 0]]])

期望的结果是:

[[3,3],[4,3],[2,1]]

您可以使用 advanced-indexing 作为广播方式对数组进行索引,就像这样 -

In [415]: val     # Data array
Out[415]: 
array([[[2, 1, 3, 0],
        [1, 0, 3, 0]],

       [[4, 1, 2, 0],
        [3, 0, 3, 0]],

       [[2, 2, 0, 0],
        [1, 1, 1, 0]]])

In [416]: idx     # Indexing array
Out[416]: 
array([[3, 3],
       [1, 1],
       [1, 1]])

In [417]: m,n = val.shape[:2]

In [418]: val[np.arange(m)[:,None],np.arange(n),idx-1]
Out[418]: 
array([[3, 3],
       [4, 3],
       [2, 1]])

np.ogrid 使用开放范围数组的更简洁的方法 -

In [424]: d0,d1 = np.ogrid[:m,:n]

In [425]: val[d0,d1,idx-1]
Out[425]: 
array([[3, 3],
       [4, 3],
       [2, 1]])

这是我使用 choose 所能做的最好的事情

In [23]: np.choose([[1,2,0],[1,2,0]], suitcounts[:,:,:3])
Out[23]: 
array([[4, 2, 3],
       [3, 1, 3]])

choose 更喜欢我们使用数组列表,而不是单个数组。它应该防止滥用。所以问题可以写成:

In [24]: np.choose([[1,2,0],[1,2,0]], [suitcounts[0,:,:3], suitcounts[1,:,:3], suitcounts[2,:,:3]])
Out[24]: 
array([[4, 2, 3],
       [3, 1, 3]])

想法是 select 来自 3 个子数组的项目,基于索引数组,如:

In [25]: np.array([[1,2,0],[1,2,0]])
Out[25]: 
array([[1, 2, 0],
       [1, 2, 0]])

输出将在形状上匹配索引数组。选择数组的形状也匹配,因此我使用 [...,:3].

第一列的值 select 来自 suitcounts[1,:,:3],第二列的值来自 suitcounts[2...] 等等

choose仅限32个选择;这是广播机制施加的限制。

说到广播我可以简化表达

In [26]: np.choose([1,2,0], suitcounts[:,:,:3])
Out[26]: 
array([[4, 2, 3],
       [3, 1, 3]])

此广播 [1,2,0] 以匹配子数组的 2x3 形状。

我可以通过对列重新排序来获得目标顺序:

In [27]: np.choose([0,1,2], suitcounts[:,:,[2,0,1]])
Out[27]: 
array([[3, 4, 2],
       [3, 3, 1]])