Numpy数组只显示唯一的行

时间:2015-11-18 17:14:49

标签: python arrays numpy unique

我想拥有一个唯一的数组行。与numpy的unique函数相反,我想排除多次出现的所有行。

所以输入:

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

应该导致输出

[[1,2],[2,3]].

我尝试使用np.unique(array, return_counts=True)计算每行的外观,然后使用>1条目过滤结果。我正在寻找一种更有效的方法来做到这一点,以及在没有返回计数的情况下做同样的事情,因为它们是在numpy 1.9之前实现的。

更新 在我的情况下,数据大小始终是[m,2],但是一旦建立了概念,它应该很容易转移到[m,n]的情况。在我的特殊情况下,数据集由整数组成,但解决方案不必限于该假设。典型的数据集将具有m ~ 10^7

2 个答案:

答案 0 :(得分:1)

方法#1

以下是使用lex-sortingnp.bincount -

的一种方法
A

请注意,输出不会保持输入数组中最初存在的元素顺序。

方法#2

如果元素是整数,那么你可以将2D数组# Convert 2D array A to a 1D array assuming each row as an indexing tuple A_1D = A.dot(np.append(A.max(0)[::-1].cumprod()[::-1][1:],1)) # Get sorting indices for the 1D array sort_idx = A_1D.argsort() # Mask of start of each unique row in 1D sorted array mask = np.append(True,np.diff(A_1D[sort_idx])!=0) # Get the counts of each unique 1D element counts = np.bincount(mask.cumsum()-1) # Select the IDs with counts==1 and thus the unique rows from A out = A[sort_idx[np.nonzero(mask)[0][counts==1]]] 转换为1D数组,假设每一行都是一个索引元组,这应该是一个非常有效的解决方案。另请注意,此方法将保持输出中元素的顺序。实施将是 -

def unq_rows_v1(A):
    sorted_idx = np.lexsort(A.T)
    sorted_Ar =  A[sorted_idx,:]
    mask = np.append(True,np.any(np.diff(sorted_Ar,axis=0),1))
    unq_count = np.bincount(mask.cumsum()-1) 
    return sorted_Ar[mask][np.nonzero(unq_count==1)[0]]

def unq_rows_v2(A):
    A_1D = A.dot(np.append(A.max(0)[::-1].cumprod()[::-1][1:],1))
    sort_idx = A_1D.argsort()
    mask = np.append(True,np.diff(A_1D[sort_idx])!=0)
    return A[sort_idx[np.nonzero(mask)[0][np.bincount(mask.cumsum()-1)==1]]]

运行时测试和验证

功能 -

In [272]: A = np.random.randint(20,30,(10000,5))

In [273]: unq_rows_v1(A).shape
Out[273]: (9051, 5)

In [274]: unq_rows_v2(A).shape
Out[274]: (9051, 5)

In [275]: %timeit unq_rows_v1(A)
100 loops, best of 3: 5.07 ms per loop

In [276]: %timeit unq_rows_v2(A)
1000 loops, best of 3: 1.96 ms per loop
时间&验证输出 -

shutdown

答案 1 :(得分:1)

numpy_indexed包(免责声明:我是它的作者)能够以完全矢量化的方式有效地解决这个问题。我已经测试了numpy但1.9,如果这仍然相关,但也许你愿意给它一个旋转让我知道。我没有任何理由相信它不适用于旧版本的numpy。

a = np.random.rand(10000, 3).round(2)
unique, count = npi.count(a)
print(unique[count == 1])

请注意,根据您的原始问题,此解决方案不限于特定数量的列或dtype。