【问题标题】:np.argsort() in tight ranknp.argsort() 排名靠前
【发布时间】:2019-08-28 11:24:05
【问题描述】:

np.argsort() 如何处理关系?

test = [1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
np.argsort(test)

为什么索引 20 在结果中排​​在第一位?

我检查了其他资源,但找不到解释。索引是随机分配的吗?谢谢!

array([20,  4,  5,  8,  9, 10, 11, 23, 17, 14, 15,  0, 22, 21, 19, 18, 12,
       13,  7,  6,  3,  2,  1, 16, 24], dtype=int64) 

【问题讨论】:

    标签: python arrays numpy sorting


    【解决方案1】:

    numpy.argsort() 返回对数组元素进行排序的数组索引。如果存在重复条目,则返回的索引取决于用于对数组进行排序的排序算法的类型。根据此选择,您可能会看到不同的结果,如下所示:

    # input
    In [90]: a
    Out[90]: 
    array([1., 1., 1., 1., 0., 0., 1., 1., 0., 0., 0., 0., 1., 1., 0., 0., 1.,
           0., 1., 1., 0., 1., 1., 0., 1.])
    
    # more intuitive
    In [85]: np.argsort(a, kind='mergesort')
    Out[85]: 
    array([ 4,  5,  8,  9, 10, 11, 14, 15, 17, 20, 23,  0,  1,  2,  3,  6,  7,
           12, 13, 16, 18, 19, 21, 22, 24])
    
    # default choice
    In [86]: np.argsort(a, kind='quicksort')
    Out[86]: 
    array([20,  4,  5,  8,  9, 10, 11, 23, 17, 14, 15,  0, 22, 21, 19, 18, 12,
           13,  7,  6,  3,  2,  1, 16, 24])
    
    In [88]: np.argsort(a, kind='heapsort')
    Out[88]: 
    array([17, 11, 20,  8, 15, 14, 23, 10,  4,  9,  5, 13,  6, 12, 24,  2, 21,
           19, 18, 16,  7, 22,  3,  1,  0])
    
    # more intuitive
    In [89]: np.argsort(a, kind='stable')
    Out[89]: 
    array([ 4,  5,  8,  9, 10, 11, 14, 15, 17, 20, 23,  0,  1,  2,  3,  6,  7,
           12, 13, 16, 18, 19, 21, 22, 24])
    

    【讨论】:

      【解决方案2】:

      其他答案提到np.argsort返回对数组进行排序的索引,并且这些索引取决于排序算法,例如:

      >>> np.random.seed(0)  # for reproducibility
      >>> a = np.random.randint(0, 5, 20)
      >>> np.argsort(a, kind='mergesort')
      array([ 2,  6,  8, 11, 16,  0,  1,  3, 12, 17, 18, 19,  9,  5,  7, 10, 13,
             14, 15,  4])
      >>> np.argsort(a, kind='quicksort')
      array([ 2, 16, 11,  6,  8,  0, 17, 12, 18, 19,  3,  1,  9, 10,  5, 13, 14,
             15,  7,  4])
      

      我想了解为什么

      简而言之,排序算法可以是稳定的,也可以是不稳定的。在这种情况下,稳定性意味着它们不会改变比较相等的元素的相对顺序

      想象我们用一些值“标记”元素以表明它们是不同的对象,例如:

      unsorted = [4 (star), 3 (cube), 3 (star), 4 (cube)]
      

      稳定的排序,例如归并排序,将总是返回以下内容:

      sorted = [3 (cube), 3 (star), 4 (star), 4 (cube)]
      

      这是因为3 (cube) 出现在3 (star) 之前,而4 (star) 出现在4 (cube) 之前。

      相反,非稳定排序(例如快速排序)可以按任何顺序返回元素,但所有 3 必须在所有 4 之前。

      当我们将此应用于我们最初的问题时,我们可以理解它为什么会出现。即使元素具有相同的 value(它们比较相等),它们也不具有相同的 identity(它们是不同的对象)。因此,在相同对象的每个“集群”中,它们可能会根据排序算法进行不同的排序。

      【讨论】:

      • 这很有趣,我一直认为这 stablenon-stable 是一个晦涩难懂的东西(可能是因为我从来没有真正关心过关系之前),但这实际上非常简单,感谢您的解释。
      【解决方案3】:

      我认为对此没有一个答案:

      >>> np.argsort(test, kind="quicksort")
      array([20,  4,  5,  8,  9, 10, 11, 23, 17, 14, ... ])
      >>> np.argsort(test, kind="mergesort")
      array([ 4,  5,  8,  9, 10, 11, 14, 15, 17, 20, ... ])
      >>> np.argsort(test, kind="stable")
      array([ 4,  5,  8,  9, 10, 11, 14, 15, 17, 20, ... ])
      >>> np.argsort(test, kind="heapsort")
      array([17, 11, 20,  8, 15, 14, 23, 10,  4,  9, ... ])
      

      我想我们可以read the code 真正理解为什么会发生这种情况,但我最好的猜测是顺序是任意的,可能是结果而不是选择。

      另一方面,如果您需要对领带进行自定义子排序,您可以使用np.unique。作为示例,我将对quicksort 的输出进行排序,使其模仿mergesort 的输出:

      ranks = np.argsort(test, kind="quicksort")
      # split the indexes so we can sort them independently:
      _, counts = np.unique(test, return_counts=True)
      cuts = np.cumsum(counts)[:-1]
      rank_bins = np.split(ranks, cuts)
      sorted_rank_bins = [np.sort(b) for b in rank_bins]
      # glue them back together: 
      ranks = np.concatenate(sorted_rank_bins)
      

      现在ranks 包含:

      array([ 4,  5,  8,  9, 10, 11, 14, 15, 17, 20, 23,  0,  1,  2,  3,  6,  7,
             12, 13, 16, 18, 19, 21, 22, 24])
      

      这个解决方案很长,我想可以有一个更短/更快的解决方案来解决这个问题。同样在这里,我只是根据它们的值对索引进行排序,但您可以想象任何其他排序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-15
        • 2023-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-06
        • 2021-12-13
        • 1970-01-01
        相关资源
        最近更新 更多