我还没有在 SO 上找到这个答案,所以我在这里分享它:
问题:当有多个排序键时,如何在 matlab 中模拟 sortrows 功能?在 matlab 中,这看起来像:
sortrows(x,[3,-4])
它首先按第三列排序,然后按第二列排序。
如果您按一列排序,您可以使用np.argsort
查找该列的索引,并应用这些索引。但是你如何为多个列做到这一点?
语法相当笨拙,看起来很奇怪,但最干净的做法是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]
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)]))