【问题标题】:numpy unique without sort [duplicate]numpy唯一没有排序[重复]
【发布时间】:2012-10-07 06:33:08
【问题描述】:

如何使用 numpy unique 而不对结果进行排序,而只是按照它们在序列中出现的顺序?像这样?

a = [4,2,1,3,1,2,3,4]

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

而不是

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

使用简单的解决方案应该可以编写一个简单的函数。但是由于我需要多次执行此操作,是否有任何快速简洁的方法来执行此操作?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    您可以使用 numpy 通过执行以下操作来执行此操作,mergsort 是稳定的,因此它可以让您挑选出每个值的第一次或最后一次出现:

    def unique(array, orderby='first'):
        array = np.asarray(array)
        order = array.argsort(kind='mergesort')
        array = array[order]
        diff = array[1:] != array[:-1]
        if orderby == 'first':
            diff = np.concatenate([[True], diff])
        elif orderby == 'last':
            diff = np.concatenate([diff, [True]])
        else:
            raise ValueError
        uniq = array[diff]
        index = order[diff]
        return uniq[index.argsort()]
    

    这个答案非常类似于:

    def unique(array):
        uniq, index = np.unique(array, return_index=True)
        return uniq[index.argsort()]
    

    但是,numpy.unique 在内部使用了不稳定的排序,因此不能保证您获得任何特定的索引,即第一个或最后一个。

    我认为有序的字典也可以工作:

    def unique(array):
        uniq = OrderedDict()
        for i in array:
             uniq[i] = 1
        return uniq.keys()
    

    【讨论】:

    • 感谢您的快速回复。我考虑过第一个,但我不确定它是否是最快的。第二个应该隐式地将一个numpy对象放入python对象中:)
    • 第二个unique 使用np.uniquereturn_index 参数是否存在问题,它可能会产生不正确的结果?这个unique 可能会返回一个序列,其中一些元素不遵守原始序列强加的顺序,例如,(纯粹用于演示)unique([1,0,1]) --> [0, 1]?
    • np.unique 的文档 (docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html) 指出使用 return_index=True 返回的索引将指示 第一次 次出现,因此您的第二次 unique 应该是安全的并且正确,对吧?
    【解决方案2】:

    您可以使用return_index 参数来做到这一点:

    >>> 将 numpy 导入为 np >>> a = [4,2,1,3,1,2,3,4] >>> np.unique(a) 数组([1, 2, 3, 4]) >>> 索引 = np.unique(a, return_index=True)[1] >>> [a[index] for index in sorted(indexes)] [4、2、1、3]

    【讨论】:

    • 链接文档总是有帮助的:numpy.unique
    • 是的,这会获取唯一索引,但是否需要排序?需要排序的迭代与仅在数组中搜索唯一项相同,因此无法避免时间复杂度。但是 numpy.unique 返回一个新的数组对象。我们应该能够避免这种空间复杂性。
    • 有效,但这确实应该作为 np.unique 的选项内置。
    • 来自this answer 只需使用pandas.unique()。默认不排序。
    • 仅供参考:this answer(上面链接)甚至使用 np.unique 提供了一个更短的解决方案(并且只调用一次):a[np.sort(np.unique(a, return_index=True)[1])]
    猜你喜欢
    • 2021-02-09
    • 2015-08-12
    • 1970-01-01
    • 2021-11-29
    • 2015-03-04
    • 1970-01-01
    • 2017-04-02
    • 2012-06-06
    • 2019-06-24
    相关资源
    最近更新 更多