我想拥有一个唯一的数组行。与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
。
答案 0 :(得分:1)
方法#1
以下是使用lex-sorting
和np.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。