假设我有一个数组
a = np.array([1, 2, 1, 3, 3, 3, 0])
我如何(有效地,Pythonically)找到哪些元素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.1s。可疑xor1d
的以 2.6s 位居第二,其次是 masking 和 PandasSeries.duplicated
的 3.1s、bincount
5.6sin1d
和 senderle 的setdiff1d
均为 7.3s。Steven 的Counter
速度稍慢一点,为 10.5 秒;紧随其后的是 Burhan 的Counter.most_common
110 秒和 DSM 的Counter
360 秒减法。
我将使用排序来提高性能,但我接受 Steven 的回答,因为性能是可以接受的,而且感觉更清晰、更 Pythonic。
编辑:发现 Pandas 解决方案。如果 Pandas 可用,它就很清楚并且性能良好。