在numpy数组中检查并索引非唯一/重复值

Car*_*l M 2 python arrays numpy unique

我有一个traced_descIDs包含对象ID 的数组,我想确定哪些项在此数组中不唯一.然后,对于每个唯一的重复(仔细)ID,我需要识别traced_descIDs与之关联的索引.

举个例子,如果我们在这里使用traced_descIDs,我希望发生以下过​​程:

traced_descIDs = [1, 345, 23, 345, 90, 1]
dupIds = [1, 345]
dupInds = [[0,5],[1,3]]
Run Code Online (Sandbox Code Playgroud)

我目前正在查找哪些对象有多个条目:

mentions = np.array([len(np.argwhere( traced_descIDs == i)) for i in traced_descIDs])
dupMask = (mentions > 1)
Run Code Online (Sandbox Code Playgroud)

然而,这需要太长时间,len( traced_descIDs )大约150,000.有没有更快的方法来实现相同的结果?

任何帮助非常感谢.干杯.

Jai*_*ime 8

虽然字典是O(n),但Python对象的开销有时使得使用numpy的函数更方便,这些函数使用排序并且是O(n*log n).在您的情况下,起点是:

a = [1, 345, 23, 345, 90, 1]
unq, unq_idx, unq_cnt = np.unique(a, return_inverse=True, return_counts=True)
Run Code Online (Sandbox Code Playgroud)

如果你使用的是早于1.9的numpy版本,那么最后一行必须是:

unq, unq_idx = np.unique(a, return_inverse=True)
unq_cnt = np.bincount(unq_idx)
Run Code Online (Sandbox Code Playgroud)

我们创建的三个数组的内容是:

>>> unq
array([  1,  23,  90, 345])
>>> unq_idx
array([0, 3, 1, 3, 2, 0])
>>> unq_cnt
array([2, 1, 1, 2])
Run Code Online (Sandbox Code Playgroud)

要获得重复的项目:

cnt_mask = unq_cnt > 1
dup_ids = unq[cnt_mask]

>>> dup_ids
array([  1, 345])
Run Code Online (Sandbox Code Playgroud)

获取索引更复杂,但非常简单:

cnt_idx, = np.nonzero(cnt_mask)
idx_mask = np.in1d(unq_idx, cnt_idx)
idx_idx, = np.nonzero(idx_mask)
srt_idx = np.argsort(unq_idx[idx_mask])
dup_idx = np.split(idx_idx[srt_idx], np.cumsum(unq_cnt[cnt_mask])[:-1])

>>> dup_idx
[array([0, 5]), array([1, 3])]
Run Code Online (Sandbox Code Playgroud)


beh*_*uri 5

scipy.stats.itemfreq哪些可以给出每个项目的频率:

>>> xs = np.array([1, 345, 23, 345, 90, 1])
>>> ifreq = sp.stats.itemfreq(xs)
>>> ifreq
array([[  1,   2],
       [ 23,   1],
       [ 90,   1],
       [345,   2]])
>>> [(xs == w).nonzero()[0] for w in ifreq[ifreq[:,1] > 1, 0]]
[array([0, 5]), array([1, 3])]
Run Code Online (Sandbox Code Playgroud)