Поиск уникальных точек в массиве numpy

Что такое более быстрый способ поиска уникальных точек x, y (удаление дубликатов) в массиве numpy, например:

points = numpy.random.randint(0, 5, (10,2))

Я думал о преобразовании точек в комплексные числа, а затем для проверки уникальности, но это кажется довольно запутанным:

b = numpy.unique(points[:,0] + 1j * points[:,1])
points = numpy.column_stack((b.real, b.imag))

Ответ 2

Думаю, у вас здесь очень хорошая идея. Подумайте о базовом блоке памяти, используемом для представления данных в points. Мы говорим numpy о том, что этот блок представляет собой массив формы (10,2) с dtype int32 (32-разрядные целые числа), но почти бесценно сказать numpy рассматривать тот же блок памяти, что и массив массивов (10) с dtype c8 (64-битный комплекс).

Итак, единственная реальная стоимость - это вызов np.unique, за которым следует еще один практически бесполезный вызов view и reshape:

import numpy as np
np.random.seed(1)
points = np.random.randint(0, 5, (10,2))
print(points)
print(len(points))

дает

[[3 4]
 [0 1]
 [3 0]
 [0 1]
 [4 4]
 [1 2]
 [4 2]
 [4 3]
 [4 2]
 [4 2]]
10

а

cpoints = points.view('c8')
cpoints = np.unique(cpoints)
points = cpoints.view('i4').reshape((-1,2))
print(points)
print(len(points))

дает

[[0 1]
 [1 2]
 [3 0]
 [3 4]
 [4 2]
 [4 3]
 [4 4]]
7

Если вам не нужен результат для сортировки, метод wim будет быстрее (вы можете подумать о принятии его ответа...)

import numpy as np
np.random.seed(1)
N=10000
points = np.random.randint(0, 5, (N,2))

def using_unique():
    cpoints = points.view('c8')
    cpoints = np.unique(cpoints)
    return cpoints.view('i4').reshape((-1,2))

def using_set():
    return np.vstack([np.array(u) for u in set([tuple(p) for p in points])])

дает следующие этапы:

% python -mtimeit -s'import test' 'test.using_set()'
100 loops, best of 3: 18.3 msec per loop
% python -mtimeit -s'import test' 'test.using_unique()'
10 loops, best of 3: 40.6 msec per loop