私は配列を持っているとします
_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データ型で動作し、中規模データセット(最大1,000万個)で効率的でなければなりません。
1000万サイズのデータセット(2.8 GHz Xeonで)を使用したテスト:
_a = np.random.randint(10**7, size=10**7)
_
最速は1.1秒でのソートです。疑わしい_xor1d
_は2.6秒で2番目で、その後にマスクとPandas _Series.duplicated
_が3.1秒、bincount
が5.6秒、_in1d
_が続きます。センダルの_setdiff1d
_両方とも7.3秒。スティーブンのCounter
は10.5秒で少し遅くなります。後ろに続くのは、110秒でのBurhanの_Counter.most_common
_と360秒でのDSMのCounter
減算です。
パフォーマンスのために並べ替えを使用しますが、パフォーマンスは許容可能であり、feelsより明確でよりPythonicなので、Stevenの答えを受け入れます。
編集:Pandasソリューションを発見しました。 Pandasが利用可能な場合、それは明確であり、うまく機能します。
これは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
を使用する方が高速です。
すでにCounter
のバリエーションが提案されていますが、listcompを使用しないものは次のとおりです。
>>> from collections import Counter
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> (Counter(a) - Counter(set(a))).keys()
[1, 3]
[投稿されたのは、それが効率的だからではなく、そうではないからです。しかし、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]
集合演算を使用する別のアプローチは、あなたが提供するものよりも少し簡単だと思います:
>>> indices = np.setdiff1d(np.arange(len(a)), np.unique(a, return_index=True)[1])
>>> a[indices]
array([1, 3, 3])
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])
これは「ヒストグラム」メソッドに非常に似ています。これは、a
が小さな整数で構成されていない場合に使用する方法です。
配列がソートされたnumpy配列の場合、次のようにします。
a = np.array([1, 2, 2, 3, 4, 5, 5, 6])
rep_el = a[np.diff(a) == 0]
Numpy以外にlibを使用したり使用したりするソリューションに適合するソリューションはないため、この3年前の質問の山にソリューションを追加しています。このメソッドは、重複のインデックスとdistinct重複セットの値の両方を見つけます。
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]
>>> 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] ]