eca*_*mur 51 python numpy unique duplicates
假设我有一个数组
a = np.array([1, 2, 1, 3, 3, 3, 0])
Run Code Online (Sandbox Code Playgroud)
我怎样(有效地,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]
Run Code Online (Sandbox Code Playgroud)
a[~np.in1d(np.arange(len(a)), np.unique(a, return_index=True)[1], assume_unique=True)]
Run Code Online (Sandbox Code Playgroud)
这个很可爱,但可能是非法的(a实际上并不是唯一的):
np.setxor1d(a, np.unique(a), assume_unique=True)
Run Code Online (Sandbox Code Playgroud)
u, i = np.unique(a, return_inverse=True)
u[np.bincount(i) > 1]
Run Code Online (Sandbox Code Playgroud)
s = np.sort(a, axis=None)
s[:-1][s[1:] == s[:-1]]
Run Code Online (Sandbox Code Playgroud)
s = pd.Series(a)
s[s.duplicated()]
Run Code Online (Sandbox Code Playgroud)
有什么我错过的吗?我不一定会寻找一个只有numpy的解决方案,但它必须使用numpy数据类型,并且对中型数据集(高达1000万的大小)有效.
使用1000万大小的数据集(在2.8GHz Xeon上)进行测试:
a = np.random.randint(10**7, size=10**7)
Run Code Online (Sandbox Code Playgroud)
排序最快的是1.1秒.可疑的xor1d是,在第二2.6S,其次是屏蔽和熊猫Series.duplicated在3.1s,bincount在5.6s,并in1d与senderle是setdiff1d在7.3s两者.史蒂文Counter只有一点点慢,10.5秒; 落后于Burhan的Counter.most_common110s和DSM的Counter减法360s.
我将使用排序来提高性能,但是我接受了Steven的回答,因为性能是可以接受的,感觉更清晰,更Pythonic.
编辑:发现了熊猫解决方案.如果Pandas可用,它很清楚并且表现良好.
Mad*_*ist 24
从numpy版本1.9.0开始,np.unique有一个参数return_counts可以大大简化你的任务:
u, c = np.unique(a, return_counts=True)
dup = u[c > 1]
Run Code Online (Sandbox Code Playgroud)
这类似于使用Counter,除了你得到一对数组而不是映射.我很想知道他们相对于彼此的表现.
Ste*_*ski 22
我认为这是最明显的做法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]
Run Code Online (Sandbox Code Playgroud)
注意: 这与Burhan Khalid的答案相似,但iteritems在条件下使用无订阅应该更快.
DSM*_*DSM 12
人们已经建议了Counter变体,但这里有一个不使用listcomp的变体:
>>> from collections import Counter
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> (Counter(a) - Counter(set(a))).keys()
[1, 3]
Run Code Online (Sandbox Code Playgroud)
[发布不是因为它有效 - 它不是 - 但因为我觉得你可以减去Counter实例很可爱.
适用于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]
Run Code Online (Sandbox Code Playgroud)
这是使用set操作的另一种方法,我认为它比你提供的方法更直接:
>>> indices = np.setdiff1d(np.arange(len(a)), np.unique(a, return_index=True)[1])
>>> a[indices]
array([1, 3, 3])
Run Code Online (Sandbox Code Playgroud)
我想你只是在寻求numpy解决方案,因为如果情况并非如此,那么仅仅使用一个Counter代替就很难.我认为你应该明确地提出这个要求.
如果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])
Run Code Online (Sandbox Code Playgroud)
这与您的“直方图”方法非常相似,如果a不是由小整数组成,我会使用这种方法。
如果数组是排序的 numpy 数组,则只需执行以下操作:
a = np.array([1, 2, 2, 3, 4, 5, 5, 6])
rep_el = a[np.diff(a) == 0]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
38880 次 |
| 最近记录: |