Numpy唯一的2D子阵列[重复]

Posted

技术标签:

【中文标题】Numpy唯一的2D子阵列[重复]【英文标题】:Numpy unique 2D sub-array [duplicate] 【发布时间】:2017-04-02 03:55:57 【问题描述】:

我有 3D numpy 数组,我只想要唯一的 2D 子数组。

输入:

[[[ 1  2]
  [ 3  4]]

 [[ 5  6]
  [ 7  8]]

 [[ 9 10]
  [11 12]]

 [[ 5  6]
  [ 7  8]]]

输出:

[[[ 1  2]
  [ 3  4]]

 [[ 5  6]
  [ 7  8]]

 [[ 9 10]
  [11 12]]]

我尝试将子数组转换为字符串(tostring() 方法),然后使用 np.unique,但在转换为 numpy 数组后,它删除了 \x00 的最后一个字节,所以我无法用 np.unique 将其转换回来。从字符串()。

例子:

import numpy as np
a = np.array([[[1,2],[3,4]],[[5,6],[7,8]],[[9,10],[11,12]],[[5,6],[7,8]]])
b = [x.tostring() for x in a]
print(b)
c = np.array(b)
print(c)
print(np.array([np.fromstring(x) for x in c]))

输出:

[b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00', b'\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00', b'\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00', b'\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00']
[b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04'
 b'\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08'
 b'\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00\x0c'
 b'\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08']

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-86-6772b096689f> in <module>()
      5 c = np.array(b)
      6 print(c)
----> 7 print(np.array([np.fromstring(x) for x in c]))

<ipython-input-86-6772b096689f> in <listcomp>(.0)
      5 c = np.array(b)
      6 print(c)
----> 7 print(np.array([np.fromstring(x) for x in c]))

ValueError: string size must be a multiple of element size

我也试过view,但我真的不知道如何使用它。 你能帮帮我吗?

【问题讨论】:

这是即将到来的 1.13 中的 new feature,如 np.unique(a, axis=0)。您可以简单地复制新的实现并在您的代码中使用它,因为 1.13 尚未发布 【参考方案1】:

一种解决方案是使用一个集合来跟踪您看到的子数组:

seen = set([])
new_a = []

for j in a:
    f = tuple(list(j.flatten()))
    if f not in seen:
        new_a.append(j)
        seen.add(f)

print np.array(new_a)

或仅使用 numpy:

print np.unique(a).reshape((len(unique) / 4, 2, 2))

>>> [[[ 1  2]
      [ 3  4]]

     [[ 5  6]
      [ 7  8]]

     [[ 9 10]
      [11 12]]]

【讨论】:

所以this answer来自上面评论的骗子 你用那个答案松开了子数组的顺序 如果一个人只是将数组复制到一个集合然后再返回到一个数组,顺序会丢失,这是真的,但是按照上面代码中的方式完成,顺序不会迷路了。【参考方案2】:

numpy_indexed 包(免责声明:我是它的作者)旨在以高效和矢量化的方式执行诸如此类的操作:

import numpy_indexed as npi
npi.unique(a)

【讨论】:

【参考方案3】:

使用@Jaime's post,为了解决我们寻找唯一二维子数组的问题,我想出了这个解决方案,它基本上为view 步骤添加了整形 -

def unique2D_subarray(a):
    dtype1 = np.dtype((np.void, a.dtype.itemsize * np.prod(a.shape[1:])))
    b = np.ascontiguousarray(a.reshape(a.shape[0],-1)).view(dtype1)
    return a[np.unique(b, return_index=1)[1]]

示例运行 -

In [62]: a
Out[62]: 
array([[[ 1,  2],
        [ 3,  4]],

       [[ 5,  6],
        [ 7,  8]],

       [[ 9, 10],
        [11, 12]],

       [[ 5,  6],
        [ 7,  8]]])

In [63]: unique2D_subarray(a)
Out[63]: 
array([[[ 1,  2],
        [ 3,  4]],

       [[ 5,  6],
        [ 7,  8]],

       [[ 9, 10],
        [11, 12]]])

【讨论】:

感谢您的回答!因此,如果我很好理解 dtype 指定大小为 a.dtype.itemsize * 子数组大小的字节序列(实际上不是任何类型)?并且需要连续数组,因为dtype指定为字节序列?对于重复的问题,我很抱歉,但我不明白@Jaime 的帖子。 @Peťan 您对第一部分是正确的。第二部分关于需要成为contiguous。我也不是很清楚。我猜可能值得对该帖子发表评论。如果我不得不猜测,我会说你的第二部分似乎合乎逻辑,但是这两部分是相关的。

以上是关于Numpy唯一的2D子阵列[重复]的主要内容,如果未能解决你的问题,请参考以下文章

将 2d numpy 数组转换为列表列表 [重复]

替换 2D numpy 数组中的连续重复项

使用数组索引的numpy数组的2D索引[重复]

在 2d numpy 中求和行 [重复]

numpy将相同子维度的矩阵堆叠在一起[重复]

使用argsort结果进行numpy索引[重复]