如何按事件对唯一的np数组元素进行排序?

时间:2019-06-12 03:06:48

标签: python python-3.x numpy sorting

我想实现以下代码:

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]

对于anp.array的情况

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

该怎么做? np.array具有np.unique()函数,用于计算每个元素的出现情况,但是我看不到如何使用它。

3 个答案:

答案 0 :(得分:2)

您可以使用np.unique及其可选参数return_countsreturn_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 :(得分:1)

您正在寻找可以与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])

答案 2 :(得分:1)

要精确模拟sorted / list的行为,可以使用@Divakar的soln进行少量修改即可使用:

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似乎暗示了)我们刚刚使用的技巧;例如参见Most efficient way to sort an array into bins specified by an index array?

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