假设我有一个数组
a = np.array([1, 2, 1, 3, 3, 3, 0])
我如何(有效地,Python地)找到a
的哪些元素是重复的(即,非唯一值)?在这种情况下,如果有效,结果将是array([1, 3, 3])
或可能array([1, 3])
。
我想出了一些似乎有用的方法:
m = np.zeros_like(a, dtype=bool)
m[np.unique(a, return_index=True)[1]] = True
a[~m]
a[~np.in1d(np.arange(len(a)), np.unique(a, return_index=True)[1], assume_unique=True)]
这个很可爱,但可能是非法的(因为a
实际上并不是唯一的):
np.setxor1d(a, np.unique(a), assume_unique=True)
u, i = np.unique(a, return_inverse=True)
u[np.bincount(i) > 1]
s = np.sort(a, axis=None)
s[:-1][s[1:] == s[:-1]]
s = pd.Series(a)
s[s.duplicated()]
有什么我错过的吗?我不一定会寻找一个只有numpy的解决方案,但它必须使用numpy数据类型,并且对中型数据集(高达1000万的大小)有效。
使用1000万大小的数据集(在2.8GHz Xeon上)进行测试:
a = np.random.randint(10**7, size=10**7)
最快的是排序,为1.1秒。可疑的xor1d
在2.6秒时排名第二,然后是3.1秒的掩蔽和熊猫Series.duplicated
,在{5.6}的bincount
,以及in1d
和发送者的setdiff1d
两者在7.3s。史蒂文的Counter
只有一点点慢,只有10.5秒;落后于Burhan的Counter.most_common
在110s和DSM的Counter
减法在360s。
我将使用排序来提高性能,但我接受了Steven的回答,因为它的性能是可以接受的,并且感觉更清晰,更Pythonic。
编辑:发现了熊猫解决方案。如果Pandas可用,它很清楚并且表现良好。
答案 0 :(得分:20)
我认为这在numpy
之外最明显。如果你担心速度问题,你必须将它与你的numpy
解决方案计时。
>>> import numpy as np
>>> from collections import Counter
>>> a = np.array([1, 2, 1, 3, 3, 3, 0])
>>> [item for item, count in Counter(a).iteritems() if count > 1]
[1, 3]
注意:这与Burhan Khalid的答案相似,但在条件下使用iteritems
而不使用下标应该更快。
答案 1 :(得分:16)
从numpy 1.9.0版开始,np.unique
具有参数return_counts
,可大大简化您的任务:
u, c = np.unique(a, return_counts=True)
dup = u[c > 1]
这与使用Counter
相似,不同之处在于您获得了一对数组而不是映射。我很想知道它们之间的相对表现。
答案 2 :(得分:12)
人们已经建议Counter
个变种,但这里有一个不使用listcomp的变种:
>>> from collections import Counter
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> (Counter(a) - Counter(set(a))).keys()
[1, 3]
[发布不是因为它有效 - 它不是 - 但因为我觉得你可以减去Counter
个实例很可爱。]
答案 3 :(得分:7)
对于Python 2.7 +
>>> import numpy
>>> from collections import Counter
>>> n = numpy.array([1,1,2,3,3,3,0])
>>> [x[1] for x in Counter(n).most_common() if x[0] > 1]
[3, 1]
答案 4 :(得分:5)
这是使用set操作的另一种方法,我认为它比你提供的方法更直接:
>>> indices = np.setdiff1d(np.arange(len(a)), np.unique(a, return_index=True)[1])
>>> a[indices]
array([1, 3, 3])
我想你要求numpy
- 只有解决方案,因为如果不是这样的话,那么仅仅使用Counter
就很难争辩。我认为你应该明确提出这个要求。
答案 5 :(得分:4)
如果a
由小整数组成,您可以直接使用numpy.bincount:
import numpy as np
a = np.array([3, 2, 2, 0, 4, 3])
counts = np.bincount(a)
print np.where(counts > 1)[0]
# array([2, 3])
这与你的“直方图”方法非常相似,如果a
不是由小整数组成,我会使用它。
答案 6 :(得分:3)
我正在为这个3岁的问题添加我的解决方案,因为除了numpy之外,没有任何解决方案符合我的要求或使用libs。此方法查找重复项的索引和不同重复项集的值。
import numpy as np
A = np.array([1,2,3,4,4,4,5,6,6,7,8])
# Record the indices where each unique element occurs.
list_of_dup_inds = [np.where(a == A)[0] for a in np.unique(A)]
# Filter out non-duplicates.
list_of_dup_inds = filter(lambda inds: len(inds) > 1, list_of_dup_inds)
for inds in list_of_dup_inds: print inds, A[inds]
# >> [3 4 5] [4 4 4]
# >> [7 8] [6 6]
答案 7 :(得分:3)
如果数组是一个有序的numpy数组,那么只需执行:
a = np.array([1, 2, 2, 3, 4, 5, 5, 6])
rep_el = a[np.diff(a) == 0]
答案 8 :(得分:0)
>>> import numpy as np
>>> a=np.array([1,2,2,2,2,3])
>>> uniques, uniq_idx, counts = np.unique(a,return_index=True,return_counts=True)
>>> duplicates = a[ uniq_idx[counts>=2] ] # <--- Get duplicates
如果您还想得到孤儿:
>>> orphans = a[ uniq_idx[counts==1] ]