【问题标题】:How to sort unique np array elements by occurence?如何按出现对唯一的 np 数组元素进行排序?
【发布时间】:2019-06-12 13:08:15
【问题描述】:

我想实现以下代码:

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 和 4 都出现了 3 次。 3s 出现在输出中的 4s 之前是否重要? IE。是否有必须满足的特殊限制条件?
  • 您的实际数据是否像您的示例中那样只包含(相对)小整数?
  • 发布的解决方案是否适合您?

标签: python python-3.x numpy sorting


【解决方案1】:

您可以使用 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])

【讨论】:

    【解决方案2】:

    要完全模仿sorted/list 的行为@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 似乎在 cmets 中暗示)可用,包括我们的稀疏矩阵技巧刚用过;例如见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
    

    【讨论】:

      【解决方案3】:

      您正在寻找 return_counts,您可以将其与 argsort + repeat 结合使用。这将保证出现相同次数的元素的顺序(注意3 之前的4,计数相同,但不是“稳定”)。


      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])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-19
        • 2016-10-11
        • 1970-01-01
        • 1970-01-01
        • 2016-02-01
        • 2015-10-18
        • 1970-01-01
        • 2015-06-28
        相关资源
        最近更新 更多