Предположим, что у меня есть массив
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]]
Pandas
s = pd.Series(a)
s[s.duplicated()]
Есть ли что-то, что я пропустил? Я не обязательно ищу решение только для numpy, но оно должно работать с типами данных numpy и быть эффективным на средних наборах данных (до 10 миллионов в размере).
Выводы
Тестирование с набором данных размером 10 миллионов (на Xeon 2.8 ГГц):
a = np.random.randint(10**7, size=10**7)
Самая быстрая сортировка - в 1.1s. Сомнительный xor1d
занимает второе место в 2.6 с, затем маскируется и Pandas Series.duplicated
в 3.1s, bincount
на 5.6s и in1d
и senderle setdiff1d
как на 7.3s. Стивен Counter
только немного медленнее, при 10,5 с; отставание отстает от Burhan Counter.most_common
при 110s и DSM Counter
вычитания при 360s.
Я собираюсь использовать сортировку для производительности, но я принимаю решение Стивена, потому что производительность приемлема, и она кажется более ясной и более Pythonic.
Изменить: обнаружено решение Pandas. Если доступно Pandas, оно очищается и работает хорошо.