检查numpy数组中的所有行是否唯一

时间:2014-03-11 23:36:59

标签: python arrays numpy

我有一个4列数组:

A=array([[100,1,500,1],
         [100,1,501,1],
         [101,1,501,1],
         [102,2,502,2],
         [500,1,100,1],
         [100,1,500,1],
         [502,2,102,2],
         [502,1,102,1]])

我想提取唯一(或第一次出现)的行和行,以便对于行i,在j的数组中没有其他行A[i,:]==A[j,[2,1,0,3]] (或第一次出现)。

因此对于数组A,我想得到一个类似于:

的数组
B=array([[100,1,500,1],
         [100,1,501,1],
         [101,1,501,1],
         [102,2,502,2],
         [502,1,102,1]])

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

A[np.unique(np.sort(A,1).view("int, int, int, int"), return_index=True)[1]]

分步骤:

In [385]: A
Out[385]: 
array([[100,   1, 500,   1],
       [100,   1, 501,   1],
       [101,   1, 501,   1],
       [102,   2, 502,   2],
       [500,   1, 100,   1],
       [100,   1, 500,   1],
       [502,   2, 102,   2],
       [502,   1, 102,   1]])

我们可以简单地通过对每一行进行排序来消除交换第0列和第2列(A[i] = A[j, [2,1,0,3])的需要。我们不必担心交换第1列和第3列,因为对于A中的所有行,我们将第1列等于第3列:A[:, 1] == A[:, 3]

In [386]: As = np.sort(A,1)

In [387]: As
Out[387]: 
array([[  1,   1, 100, 500],
       [  1,   1, 100, 501],
       [  1,   1, 101, 501],
       [  2,   2, 102, 502],
       [  1,   1, 100, 500],
       [  1,   1, 100, 500],
       [  2,   2, 102, 502],
       [  1,   1, 102, 502]])

As(排序数组)中查找唯一行。将其视为结构化数组,其中每一行都是单个元素(因为np.unique将首先展平数组)

In [388]: As.view('int, int, int, int')
Out[388]: 
array([[(1, 1, 100, 500)],
       [(1, 1, 100, 501)],
       [(1, 1, 101, 501)],
       [(2, 2, 102, 502)],
       [(1, 1, 100, 500)],
       [(1, 1, 100, 500)],
       [(2, 2, 102, 502)],
       [(1, 1, 102, 502)]], 
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8')])

In [389]: u, i = np.unique(As.view('int, int, int, int'), return_index=True)

In [390]: i
Out[390]: array([0, 1, 2, 7, 3])

并使用它们从原始数组As中获取A中唯一的行:

In [391]: A[i]
Out[391]: 
array([[100,   1, 500,   1],
       [100,   1, 501,   1],
       [101,   1, 501,   1],
       [502,   1, 102,   1],
       [102,   2, 502,   2]])

答案 1 :(得分:0)

对于唯一行,您可以使用python集删除重复项。由于np数组(或列表)不可用,您可能必须在选择时将行转换为元组,然后转换回数组:

B = np.array(list(set([tuple(x) for x in A])))

对于问题的第二部分,您需要实现自己的选择循环:

B = []
for row in A:
    lrow = list(row)
    if lrow not in B and [lrow[2], lrow[1], lrow[0], lrow[3]] not in B:
        B.append(lrow)
B = np.array(B)

答案 2 :(得分:0)

我不明白问题的第二部分意味着什么(启动A [i:]的部分)但是作为一个简单的循环你也可以使用

B = []
for data in A:
  if data not in B:
    B.append(data)
tuple(B)

这将循环通过A,检查它是否已经在B中并附加它。这不是最有效的方法,因为你需要每次循环B,但它很简单明了。

你是否要求数据= [0,1,2,3]不存在像[2,0,1,3]这样的行

如果是这种情况,则添加到if

and [data[2], data[0], data[1], data[3]] not in B

我认为将其设置为树和分支处理可能会有效。也就是说,在A [0]处通过A [1]的值创建分支。然后是A [2]的分支和A [3]处的叶子。在最后的叶子上,如果叶子已经存在则丢弃它。一旦构建了树结构,返回并收集所有分支和叶子到数组结构中,根据定义,它们将是唯一的。在任何情况下,这都需要读取初始列表一次,并且不需要为A中的每一行完全读取B列表。我没有时间弄清楚如何用Python而不是视觉流程图来表达它。也许它可以作为一组词典工作,但我不确定。

{A[0]:{A[1]:{A[2]:{A[3]:True}}}}

不起作用,因为它会覆盖密钥的值。也许每个键和子键的字典列表是可能的,给出一组键A [1]的字典和键A [2]的字典列表

在读取每个条目时,如果在特定列表中找不到A [3],则追加它。如果找到它,则它是重复的。我认为基数将是

的顺序
{A[0]:({A[1]:({A[2]:(A[3])})})}

我不知道这个概念是否有效,但需要适当的for循环和附加,并且可能太复杂而无法设置。