使用两个参数对numpy数组进行排序

时间:2018-05-03 20:18:33

标签: python sorting numpy

我拥有的一小段数据集如下:

import numpy

fns = numpy.array(["filename_0004_0003_info.hdf5", "filename_0003_0003_info.hdf5", "filename_0001_0001_info.hdf5", "filename_0002_0001_info.hdf5", "filename_0006_0002_info.hdf5", "filename_0005_0002_info.hdf5"])

我称之为run的第一个整数,而第二个整数I表示为order。我想对这个数据集进行排序。首先基于order号码,第二个基于run号码。每个order号码都存在两次,而run号码是唯一的。当我仅使用order时基于numpy.argsort()数字进行排序:

order_nrs = numpy.array([int(fn.split("_")[2]) for fn in fns])
fns = numpy.copy(fns)[numpy.argsort(order_nrs)]

我获得了

['filename_0001_0001_info.hdf5' 'filename_0002_0001_info.hdf5' 'filename_0006_0002_info.hdf5' 'filename_0005_0002_info.hdf5' 'filename_0004_0003_info.hdf5' 'filename_0003_0003_info.hdf5']

虽然fns基于order排序,但之后也应按run排序。结果应该是:

filename_0001_0001_info.hdf5
filename_0002_0001_info.hdf5
filename_0005_0002_info.hdf5
filename_0006_0002_info.hdf5
filename_0003_0003_info.hdf5
filename_0004_0003_info.hdf5

我如何实现这一目标?

4 个答案:

答案 0 :(得分:0)

fns = ["filename_0004_0003_info.hdf5", "filename_0003_0003_info.hdf5", "filename_0001_0001_info.hdf5", "filename_0002_0001_info.hdf5", "filename_0006_0002_info.hdf5", "filename_0005_0002_info.hdf5"]


def sortfunc(s):
    words = s.split('_')
    run, order = int(words[1]), int(words[2])
    return order, run

fns.sort(key=sortfunc)

答案 1 :(得分:0)

有点冗长,但看​​到'命令' argsort中的参数。

fns = np.array(["filename_0004_0003_info.hdf5", "filename_0003_0003_info.hdf5", "filename_0001_0001_info.hdf5", "filename_0002_0001_info.hdf5",
     "filename_0006_0002_info.hdf5", "filename_0005_0002_info.hdf5"])

o = np.array([fn.split("_") for fn in fns])
a_r = np.core.records.fromarrays(o.transpose(),
                                     names=['a', 'b', 'c', 'd'],
                                     formats=['U9']*4)
idx = np.argsort(a_r, order=['c', 'b'])

out = fns[idx]

out
Out[22]: 
array(['filename_0001_0001_info.hdf5', 'filename_0002_0001_info.hdf5',
       'filename_0005_0002_info.hdf5', 'filename_0006_0002_info.hdf5',
       'filename_0003_0003_info.hdf5', 'filename_0004_0003_info.hdf5'],
      dtype='<U28')

从文件名开始,像你一样在_上拆分,转换为重新排列或结构化数组(给出一个简单的例子),使用argsort但是对你想要使用的两个数字类型进行排序。 。并使用idx索引对原始内容进行重新排序。 可能还有其他优雅的方式,但我喜欢看到发生了什么,argsort订单属性让我清楚。糟糕的是,你不能使用索引号而不是命名字段

答案 2 :(得分:0)

一种方法是设计dtype,使得只有两个数字可见,第二个数字首先出现:

>>> fns = numpy.array(["filename_0004_0003_info.hdf5", "filename_0003_0003_info.hdf5", "filename_0001_0001_info.hdf5", "filename_0002_0001_info.hdf5", "filename_0006_0002_info.hdf5", "filename_0005_0002_info.hdf5"])
>>> fns.view(np.dtype({'names':['f1','f2'], 'formats':['<U4','<U4'], 'offsets':[56,36], 'itemsize':112})).sort()
>>> fns
array(['filename_0001_0001_info.hdf5', 'filename_0002_0001_info.hdf5',
       'filename_0005_0002_info.hdf5', 'filename_0006_0002_info.hdf5',
       'filename_0003_0003_info.hdf5', 'filename_0004_0003_info.hdf5'],
      dtype='<U28')

这是直接就地排序,但argsort当然也有效。

答案 3 :(得分:0)

查看np.lexsort,它会在一系列键上使用稳定排序来执行您想要的操作。