numpy.unique
сортирует свой аргумент, поэтому его временная сложность равна O (n * log (n)).Похоже, класс Counter
может быть O (n).
Если значения в ваших массивах являются неотрицательными целыми числами, которые не слишком велики, эта версия довольно быстрая:
def pairs_frequency3(x, y, maxval=15):
z = maxval*x + y
counts = np.bincount(z)
pos = counts.nonzero()[0]
ux, uy = np.divmod(pos, maxval)
return counts[pos], ux, uy
Установите maxval
на 1 плюс максимальное значение в x
и y
.(Вы можете удалить аргумент и добавить код, чтобы найти максимум в функции.)
Время (x
и y
были сгенерированы, как в вопросе):
In [13]: %timeit pairs_frequency(x, y)
13.8 ms ± 77.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [14]: %timeit pairs_frequency2(x, y)
32.9 ms ± 631 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [15]: %timeit pairs_frequency3(x, y)
129 µs ± 1.03 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Обратите внимание на изменение в единицах времени третьего результата.
pairs_frequency3
возвращает массивы в том же порядке, что и pairs_frequency2
, поэтому легко проверить, что они возвращают одинаковые значения:
In [26]: counts2, x2, y2 = pairs_frequency2(x, y)
In [27]: counts3, x3, y3 = pairs_frequency3(x, y)
In [28]: np.all(counts2 == counts3) and np.all(x2 == x3) and np.all(y2 == y3)
Out[28]: True