首页 > 解决方案 > 如何返回一个numpy数组,其值来自相同形状的不同数组的最大值的源数组

问题描述

我很难写出这个问题,所以也许最好只是为了说明。简而言之,我有两组相同形状的三个数组。使用第一组,对于每个元素,我想找到哪个数组在该位置具有最大值并返回第二组的值。虽然该示例将每个 3 x 3 形状的阵列作为不同的对象,但它们也可以很容易地成为 (3 ,3 ,3)。

找到最大值的集合:

import numpy as np
A1 = np.array([[13, 16, 17], [32, 16, 11], [46, 30, 14]], dtype='uint8')
B1 = np.array([[31, 46, 41], [19, 29, 45], [36, 30, 46]], dtype='uint8')
C1 = np.array([[36, 35, 26], [19, 40, 24], [5, 20, 46]], dtype='uint8') 

用作返回值的集合:

A2 = np.array([[1, 1, 4], [3, 1, 4], [1, 3, 2]], dtype='uint8')
B2 = np.array([[2, 3, 1], [4, 4, 2], [1, 1, 3]], dtype='uint8')
C2 = np.array([[3, 2, 3], [1, 2, 3], [2, 4, 4]], dtype='uint8')

如果它是一个两步解决方案,第一个将返回一个数组,如:

mx1
array([['C', 'B', 'B'],
       ['A', 'C', 'B'],
       ['A', 'A', 'B']], dtype='<U1')

那么所需的输出是:

out1
array([[3, 3, 1],
       [3, 2, 2],
       [1, 3, 3]])

请注意,如果最大值(最后两个元素)出现平局,则第一个遇到的数组中的值是可接受的值。

我认为这将是一个使用一些 np.max 和 np.where 类型魔法的简单任务,但我似乎无法正确解决这个问题。

标签: pythonarraysnumpy

解决方案


import numpy as np

A1 = np.array([[13, 16, 17], [32, 16, 11], [46, 30, 14]], dtype='uint8')
B1 = np.array([[31, 46, 41], [19, 29, 45], [36, 30, 46]], dtype='uint8')
C1 = np.array([[36, 35, 26], [19, 40, 24], [5, 20, 46]], dtype='uint8') 

A2 = np.array([[1, 1, 4], [3, 1, 4], [1, 3, 2]], dtype='uint8')
B2 = np.array([[2, 3, 1], [4, 4, 2], [1, 1, 3]], dtype='uint8')
C2 = np.array([[3, 2, 3], [1, 2, 3], [2, 4, 4]], dtype='uint8')

D=np.array([A1,B1,C1])
F=np.array([A2,B2,C2])

amax=np.argmax(D,axis=0)
# array( [[2, 1, 1],
#         [0, 2, 1],
#         [0, 0, 1]] )

#There should be a better way to do this.
idx=np.array([ (y,x[0],x[1]) for x,y in np.ndenumerate(amax)])
# array([[2, 0, 0],
#        [1, 0, 1],
#        [1, 0, 2],
#        [0, 1, 0],
#        [2, 1, 1],
#        [1, 1, 2],
#        [0, 2, 0],
#        [0, 2, 1],
#        [1, 2, 2]] )

flat_answer=F[(idx[:,0],idx[:,1 ],idx[:,2])]
# array( [3, 3, 1, 3, 2, 2, 1, 3, 3] )

answer = np.reshape(flat_answer,np.shape(amax)))
# array( [[3, 3, 1],
#         [3, 2, 2],
#         [1, 3, 3]] )

诀窍是制作一个 3D 数组,形成A1, A2, A3。然后用于argmax()获取正确的索引。

我确信有一种“智能”的 numpy 索引方法可以根据argmax()结果减少 F 的维度。但是我的解决方法是使用并列出理解来通过多维索引ndenumerate()构建具有正确值的扁平数组,然后再次将其重新整形。(3,3)


编辑,更好的解释:

ndenumerate()返回一个元组生成器,其中包含数组中每个位置的坐标和值,即。对于数组

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

它将返回元组:

( ( 0, 0 ), 1 )
( ( 0, 1 ), 2 )
( ( 1, 0 ), 3 )
( ( 1, 1 ), 4 )

但是 的值amax已经是 和 的第 3 维坐标DF所以我们连接 的输出ndenumerate(amax)来构建 的坐标F

ndenumerate        coordinate
((x1, x2 ), v ) -> (v, x1, x2)

最后两行代码,使用坐标将答案从 3x3x3 数组投影F到 3x3answer使用 numpy 索引规则。

相当于做如下映射:

clearer_answer = np.zeros(np.shape(amax))
for x,y in np.ndenumerate(amax):
    clearer_answer[x] = F[(y,x[0],x[1])]

推荐阅读