简体   繁体   English

将现有的Numpy ndarray的值转换为元组

[英]Converting values of Existing Numpy ndarray to tuples

Let's say I have a numpy.ndarray with shape (2,3,2) as below, 假设我有一个shape (2,3,2)numpy.ndarray ,如下所示,

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

I want to reshape it in such a way that: 我想通过以下方式重塑它:

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

and each value of arr is a size 2 tuple 并且arr每个值都是一个大小为2的tuple

The reason I want to do this is that I want to take the minimum along axis 0 of the 3dimensional array, but I want to preserve the value that the min of the rows in paired with. 我要这样做的原因是,我想沿3维数组的轴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]]

If the array contained tuples, it would be 2 dimensional, and the comparison operator for minimize would still function correctly, so I would get the correct result. 如果数组包含元组,它将是2维的,并且minimum的比较运算符仍然可以正常运行,因此我将获得正确的结果。 But I haven't found any way to do this besides iterating over the arrays, which is inefficient and obvious in implementation. 但是除了遍历数组外,我没有找到任何其他方法可以做到这一点,这在执行中效率低下并且显而易见。

Is it possible to perform this conversion efficiently in numpy? 是否可以在numpy中有效地执行此转换?

Don't use tuples at all - just view it as a structured array, which supports the lexical comparison you're after: 根本不使用元组-只需将其视为结构化数组即可,它支持您要进行的词法比较:

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')])

First, let's find out which pairs to take: 首先,让我们找出采用哪些对:

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

Here, first_eq is True where the first elements match, so we would need to compare the second elements. 在这里, first_eq在第一个元素匹配的地方为True,因此我们需要比较第二个元素。 It's [False, False, False] in your example. 在您的示例中为[False, False, False] which_compare then is [0, 0, 0] (because the first element of each pair is what we will compare). 那么which_compare[0, 0, 0] (因为每对的第一个元素就是我们要比较的元素)。 Finally, winner tells us which of the two pairs to choose along the second axis. 最后, winner告诉我们沿着第二根轴选择哪一对。 It is [0, 0, 1] . 它是[0, 0, 1]

The last step is to extract the winners: 最后一步是提取获奖者:

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

That is, take the winner (0 or 1) at each point along the second axis. 也就是说,沿第二条轴在每个点上取胜者(0或1)。

Here's one way - 这是一种方法-

# 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])]

Sample run - 样品运行-

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]])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM