【问题标题】:How to sort numpy arrays in arrays?如何对数组中的numpy数组进行排序?
【发布时间】:2014-05-27 14:20:31
【问题描述】:

这个问题与this one 密切相关。有人可以说它可以通过np.lexsort 或在np.recarray 上排序来解决,但不是以一种琐碎和pythonic 的方式。

我有一个 numpy 数组,例如这个:

array([[[  2,  7,  1],
        [ 35,  9,  1],
        [ 22, 12,  4]],

       [[ 12,  2,  3],
        [  3,  7,  8],
        [ 12,  1, 10]]])

我很想把它作为输出:

array([[[  2,  7,  1],
        [ 22, 12,  4],
        [ 35,  9,  1]],

       [[  3,  7,  8],
        [ 12,  1, 10],
        [ 12,  2,  3]]])

也就是说,根据每个内部数组的第一个、第二个和第三个值对它们进行排序。请注意,我不想按列排序(没有类似表格的排序)。这是想要的:

array([[[  2,  7,  1],
        [ 22,  9,  1],
        [ 35, 12,  4]],

       [[  3,  1,  3],
        [ 12,  2,  8],
        [ 12,  7, 10]]])

换句话说,我想要的是np.sort_complex,但对于更高维复杂的类型。

对我来说,更明智的方法是从我的 3D 数组中创建一个np.recarray。问题是我不知道如何以便宜的方式做到这一点。您将如何快速转换此处显示的数组之一:

array([[(  2,  7,  1),
        ( 35,  9,  1),
        ( 22, 12,  4)],

       [( 12,  2,  3),
        (  3,  7,  8),
        ( 12,  1, 10)]], dtype=???)

具有正确的 dtype ([("c1", "f8"), ("c2", "f8"), ("c3", "f8")]-like 但考虑到更高的维度)?

np.lexarray 对高维数组的行为非常奇怪,我无法让它工作。

np.argsort 也不是答案,因为它的排序方式不稳定(没有“抽奖”总是第一、第二和第三)。

我在纯 python 中提出了一个非常缓慢的“解决方案”,还有其他想法吗?

【问题讨论】:

    标签: python arrays sorting numpy


    【解决方案1】:

    有很多事情可能会出错,稍后会详细介绍,但在您的情况下,您可以以非常简单的方式对数组进行排序:

    >>> a = np.array([[[  2,  7,  1],
    ...                [ 35,  9,  1],
    ...                [ 22, 12,  4]],
    ... 
    ...               [[ 12,  2,  3],
    ...                [  3,  7,  8],
    ...                [ 12,  1, 10]]])
    >>> a_view = a.view(dtype=[('', a.dtype)]*a.shape[-1])
    >>> a_view.sort(axis=1)
    >>> a
    array([[[ 2,  7,  1],
            [22, 12,  4],
            [35,  9,  1]],
    
           [[ 3,  7,  8],
            [12,  1, 10],
            [12,  2,  3]]])
    

    为此,您要用于解决绘图的轴必须是最后一个数组,并且该数组必须是连续的。因此,无论a 的历史如何,要做到这一点,使用a = np.ascontiguousarray(a) 可能是安全的做法。

    【讨论】:

    • 这对我来说似乎很棒。至少我现在知道如何将这样的数组描述为 rec 数组。非常感谢。
    【解决方案2】:

    您可以使用小列表推导和lexsort()

    np.array([b[np.lexsort(b[:,::-1].T)] for b in a])
    #array([[[ 2,  7,  1],
    #        [22, 12,  4],
    #        [35,  9,  1]],
    # 
    #       [[ 3,  7,  8],
    #        [12,  1, 10],
    #        [12,  2,  3]]])
    

    【讨论】:

    • 啊!在对数组进行 lexsorting 之前,我忘了反转数组!因此出现了奇怪的行为。
    猜你喜欢
    • 2015-01-10
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多