Как отсортировать уникальные элементы массива np по происхождению? - PullRequest
3 голосов
/ 12 июня 2019

Я хотел бы реализовать следующий код:

a = [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
sorted(a,key=a.count,reverse=True)
>>> [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

Для случая, когда a является np.array

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

Как это сделать? У np.array есть функция np.unique(), которая вычисляет вхождение каждого элемента, но я не вижу, как я могу использовать это здесь.

Ответы [ 3 ]

2 голосов
/ 12 июня 2019

Вы можете использовать np.unique с необязательными аргументами return_counts и return_inverse -

u, ids, c = np.unique(a, return_counts=True, return_inverse=True)
out = a[c[ids].argsort()[::-1]]

Пример выполнения -

In [90]: a = np.array([1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5])

In [91]: u, ids, c = np.unique(a, return_counts=True, return_inverse=1)

In [92]: a[c[ids].argsort()[::-1]]
Out[92]: array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])
1 голос
/ 12 июня 2019

Чтобы точно имитировать sorted / list поведение @ Solv Divakar может использоваться с небольшой модификацией:

al = [1,2,3,2,1,3,2]
aa = np.array(al)

sorted(al, key=al.count, reverse=True)
# [2, 2, 2, 1, 3, 1, 3]

u, ids, c = np.unique(aa, return_counts=True, return_inverse=True)
aa[(-c[ids]).argsort(kind="stable")]
# array([2, 2, 2, 1, 3, 1, 3])

Если aa большой,

from scipy import sparse
sparse.csc_matrix((aa, (c.max()-c[ids]), np.arange(len(ids)+1))).tocsr().data
# array([2, 2, 2, 1, 3, 1, 3], dtype=int64)

может быть немного быстрееНемного, однако, потому что в обоих случаях мы сначала называем дорогой unique, если только данные не являются слишком большими целыми числами, и в этом случае доступны более быстрые альтернативы (на которые @WarrenWeckesser ссылается в комментариях), включая уловку разреженной матрицы, которую мытолько что использовал;см., например, Самый эффективный способ сортировки массива по бинам, заданным индексным массивом? .

aaa = np.tile(aa,10000)
timeit(lambda:aaa[(-c[ids]).argsort(kind="stable")], number=10)
# 0.040545254945755005
timeit(lambda:sparse.csc_matrix((aaa, (c.max()-c[ids]), np.arange(len(ids)+1))).tocsr().data, number=10)
# 0.0118721229955554
1 голос
/ 12 июня 2019

Вы ищете return_counts, который вы можете объединить с argsort + repeat.Это не гарантирует порядок элементов, которые появляются одинаковое количество раз (обратите внимание на 4 перед 3, то же количество, но не "стабильно").


u, c = np.unique(a, return_counts=True)
i = np.argsort(c)[::-1]
np.repeat(u[i], c[i])

array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...