1. ホーム
  2. python

配列内の重複する値の判定

2023-09-16 23:30:42

質問

例えば、以下のような配列があるとします。

a = np.array([1, 2, 1, 3, 3, 3, 0])

の要素を見つけるにはどうしたらよいでしょうか? 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万サイズ)で効率的である必要があります。


結論

1,000 万サイズのデータセットでテスト (2.8GHz Xeon 上)。

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

一番速いのはソートで、1.1秒です。 怪しげな xor1d が2.6秒で2位、次いでマスキングとPandasの Series.duplicated が3.1sで続いています。 bincount が5.6秒、そして in1d とセンダルの setdiff1d はともに7.3秒。 スティーブンの Counter は10.5秒と少し遅く、その後ろにいるのはBurhanの Counter.most_common が110秒台、DSMの Counter を360sで引き算します。

パフォーマンスのためにソートを使うつもりですが、スティーブンの答えを受け入れるのは、パフォーマンスが許容範囲内であることと が感じられます。 より明確で、よりPythonicに感じられるからです。

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

をメモしてください。 これはBurhan Khalidの答えと似ていますが、使用されているのは items を使用した方が速いでしょう。