如何在numpy数组中对数组进行排序?

3
这个问题与这个问题密切相关。可以使用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但适用于更高维度的复合类型。
对我来说,更明智的方法是从我的三维数组创建一个np.recarray。问题是我不知道怎么以便宜的方式做到这一点。您如何快速转换其中一个在此处显示的数组:
array([[(  2,  7,  1),
        ( 35,  9,  1),
        ( 22, 12,  4)],

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

使用正确的数据类型 ([("c1", "f8"), ("c2", "f8"), ("c3", "f8")]-类似但考虑更高维度)?

在处理高维数组时,np.lexarray 的行为相当奇怪,我无法使其正常工作。

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

我想出了一个纯Python的“解决方案”,但速度非常慢,还有其他的想法吗?
2个回答

3

有很多事情可能会出错,稍后再详细说明,但在您的情况下,您可以非常轻松地按照自己的意愿对数组进行排序:

>>> 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)可能是安全的。


这对我来说很棒。至少现在我知道如何将这样的数组描述为一个记录数组。非常感谢你。 - user1940040

0
你可以使用一个小的列表推导式和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]]])

1
啊!我忘记在进行词典排序之前反转数组了!这就是出现奇怪行为的原因。 - user1940040

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接