6

我还没有在 SO 上找到这个答案,所以我在这里分享它:

问题:当有多个排序键时,如何在 matlab 中模拟 sortrows 功能?在 matlab 中,这看起来像:

sortrows(x,[3,-4])

它首先按第三列排序,然后按第二列排序。

如果您按一列排序,您可以使用np.argsort查找该列的索引,并应用这些索引。但是你如何为多个列做到这一点?

4

2 回答 2

5

语法相当笨拙,看起来很奇怪,但最干净的做法是np.lexsort.

data = np.array([[3, 0, 0, .24],
                 [4, 1, 1, .41],
                 [2, 1, 1, .63],
                 [1, 1, 3, .38]]) #imagine rows of a spreadsheet
#now do sortrows(data,[3,-4])
ix = np.lexsort((data[:, 3][::-1], data[:, 2])) 
#this yields [0, 2, 1, 3]

#note that lexsort sorts first from the last row, so sort keys are in reverse order

data[ix]
于 2013-09-20T15:03:29.587 回答
0

EDIT2:由于python中的负数是有意义的,我认为它们不应该用于指定列的降序,因此我在这里使用了一个辅助降序对象。

import numpy as np

class Descending:
    """ for np_sortrows: sort column in descending order """
    def __init__(self, column_index):
        self.column_index = column_index

    def __int__(self):  # when cast to integer
        return self.column_index


def np_sortrows(M, columns=None):
    """  sorting 2D matrix by rows
    :param M: 2D numpy array to be sorted by rows
    :param columns: None for all columns to be used,
                    iterable of indexes or Descending objects
    :return: returns sorted M
    """
    if len(M.shape) != 2:
        raise ValueError('M must be 2d numpy.array')
    if columns is None:  # no columns specified, use all in reversed order
        M_columns = tuple(M[:, c] for c in range(M.shape[1]-1, -1, -1))
    else:
        M_columns = []
        for c in columns:
            M_c = M[:, int(c)]
            if isinstance(c, Descending):
                M_columns.append(M_c[::-1])
            else:
                M_columns.append(M_c)
        M_columns.reverse()

    return M[np.lexsort(M_columns), :]

data = np.array([[3, 0, 0, .24],
                 [4, 1, 1, .41],
                 [2, 1, 3, .25],
                 [2, 1, 1, .63],
                 [1, 1, 3, .38]])

# third column is index 2, fourth column in reversed order at index 3    
print(np_sortrows(data, [2, Descending(3)]))
于 2019-02-27T17:07:57.797 回答