将Existing Numpy ndarray的值转换为元组

时间:2017-10-01 08:36:43

标签: python numpy

假设我numpy.ndarray shape (2,3,2)如下,

arr = np.array([[[1,3], [2,5], [1,2]],[[3,3], [6,5], [5,2]]])

我想以这样的方式重塑它:

arr.shape == (2,3)
arr == [[(1,3), (2,5), (1,2)],[(3,3), (6,5), (5,2)]]

arr的每个值都是2 tuple

我想这样做的原因是我想沿着3dimensional数组的轴0取最小值,但我想保留与行配对的最小值的值。

arr = np.array(
  [[[1, 4],
    [2, 1],
    [5, 2]],

   [[3, 3],
    [6, 5],
    [1, 7]]])

print(np.min(arr, axis=0))
>>> [[1,3], 
     [2,1],
     [1,2]]
>>>Should be
    [[1,4],
     [2,1],
     [1,7]]

如果数组包含元组,那么它将是2维的,并且用于最小化的比较运算符仍然可以正常运行, 所以我会得到正确的结果。但是除了迭代数组之外,我还没有找到任何方法来实现这一点,这在实现中是低效且明显的。

是否可以在numpy中有效地执行此转换?

3 个答案:

答案 0 :(得分:3)

根本不使用元组 - 只需将其视为结构化数组,它支持您之后的词汇比较:

a = np.array([[[1,3], [2,5], [1,2]],[[3,3], [6,5], [5,2]]])

a_pairs = a.view([('f0', a.dtype), ('f1', a.dtype)]).squeeze(axis=-1)
min_pair = np.partition(a_pairs, 0, axis=0)[0]  # min doesn't work on structured types :(
array([(1, 4), (2, 1), (1, 7)], 
      dtype=[('f0', '<i4'), ('f1', '<i4')])

答案 1 :(得分:1)

首先,让我们找出要采取的对:

first_eq = arr[0,:,0] == arr[1,:,0]
which_compare = np.where(first_eq, 1, 0)[0]
winner = arr[:,:,which_compare].argmin(axis=0)

这里,first_eq为True,其中第一个元素匹配,因此我们需要比较第二个元素。你的例子中是[False, False, False]which_compare然后是[0, 0, 0](因为每对的第一个元素是我们要比较的)。最后,winner告诉我们沿着第二轴选择哪两对。它是[0, 0, 1]

最后一步是提取获奖者:

arr[winner, np.arange(arr.shape[1])]

即,沿第二轴的每个点取得胜利者(0或1)。

答案 2 :(得分:1)

这是一种方式 -

# Get each row being fused with scaling based on scale being decided
# based off the max values from the second col. Get argmin indices.
idx = (arr[...,1] + arr[...,0]*(arr[...,1].max()+1)).argmin(0)

# Finally use advanced-indexing to get those rows off array
out = arr[idx, np.arange(arr.shape[1])]

示例运行 -

In [692]: arr
Out[692]: 
array([[[3, 4],
        [2, 1],
        [5, 2]],

       [[3, 3],
        [6, 5],
        [5, 1]]])

In [693]: out
Out[693]: 
array([[3, 3],
       [2, 1],
       [5, 1]])