我想实现以下代码:
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()
函数,用于计算每个元素的出现情况,但是我看不到如何使用它。
答案 0 :(得分:2)
您可以使用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 :(得分: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