假设我有一个数组
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]
Set 操作
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]]
Pandas
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秒,接下来是掩码和Pandas的Series.duplicated
,需要3.1秒;bincount
需要5.6秒,而in1d
和senderle的setdiff1d
都需要7.3秒。Steven的Counter
稍微慢一点,需要10.5秒;Burhan的Counter.most_common
需要110秒,而DSM的Counter
减法则需要360秒。
我将使用排序以获得更好的性能,但我选择接受Steven的答案,因为它看起来更加清晰和符合Pythonic风格。
编辑:发现了Pandas的解决方案。如果有Pandas可用,则该解决方案效果明显且性能良好。
s[:-1][ s[1:] == s[:-1] ]
吗?否则我会得到一个IndexError
,因为布尔掩码比s
数组少一个元素... - snake_charmernumpy array
,则可以起作用。 - Godrebh