确定数组中的重复值

发布于 2021-01-29 18:00:02

假设我有一个数组

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万个大小)上有效。


结论

使用一千万个大小的数据集(在2.8GHz Xeon上)进行测试:

a = np.random.randint(10**7, size=10**7)

最快的是排序,速度为1.1秒。可疑xor1dSeries.duplicated以2.6秒排名第二,其次是面具和熊猫,分别bincount为3.1秒in1d和5.6秒,以及哨兵的setdiff1d两者均为7.3秒。史蒂文的Counter速度稍慢一点,为10.5秒。紧随其后的是Burhan的Counter.most_common110年代和DSM的Counter减法360年代。

我将使用排序来提高性能,但我接受Steven的回答,因为性能是可以接受的,并且 感觉 更加清晰和Pythonic。

编辑:发现了熊猫解决方案。如果有Pandas可用,那就很清楚并且表现良好。

关注者
0
被浏览
46
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我认为这是在之外最明确的做法numpynumpy如果您担心速度,则必须将其与解决方案放在一起。

    >>> 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).items() if count > 1]
    [1, 3]
    

    注意: 这与Burhan Khalid的答案类似,但items在这种情况下不带下标的使用应更快。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看