如何根据numpy的argsort函数的输出对列表进行排序

3

我有一个类似这样的列表:

 myList = [10,30,40,20,50]

现在我使用numpyargsort函数来获取排序列表的索引:
import numpy as np
so = np.argsort(myList)

这将会给我输出:

array([0, 3, 1, 2, 4])

当我想要使用sort对数组进行排序时,它可以正常工作:

myArray = np.array([1,2,3,4,5])
myArray[so]
array([1, 4, 2, 3, 5])

但是当我将它应用到另一个列表时,它却无法工作并且抛出错误。
myList2 = [1,2,3,4,5]
myList2[so]

类型错误:只有包含一个元素的整数数组可以转换为索引。

我如何在不使用for循环并且不先将此列表转换为数组的情况下,现在使用so来对另一个列表进行排序?


这已经是一个很好的例子,演示了如何根据第一个列表对第二个列表进行排序。它使用多列排序表格,但只对有序的第二列感兴趣。 - pas-calc
2个回答

5

myList2 是一个普通的 Python 列表,它不支持这种类型的索引。

你需要将其转换为 numpy.array,例如 -

In [8]: np.array(myList2)[so]
Out[8]: array([1, 4, 2, 3, 5])

或者你可以使用列表推导式 -

In [7]: [myList2[i] for i in so]
Out[7]: [1, 4, 2, 3, 5]

是的,首先将其转换为数组可能是一个选项,但这是我想避免的。看来我会选择列表推导式... 如果没有更好的解决方案,我会点赞并稍后接受它。 - Cleb
1
@Cleb 我认为列表推导式是你能得到的最好的。除非你更喜欢更函数式风格的 map(myList2.__getitem__, so),但在Python中看起来很糟糕。 - loopbackbee
@goncalopp:是的,我想我会采用它。我只是喜欢切片、使用索引等等,所以我想知道是否有一种方法可以做到这一点。 - Cleb

3

你不能直接将其转换为数组,然后再转回去。

myListSorted = list(np.array(myList)[so])

编辑:我进行了一些基准测试,比较了NumPy方法和列表推导式的性能。NumPy快了约27倍。

>>> from timeit import timeit
>>> import numpy as np

>>> myList = list(np.random.rand(100))
>>> so = np.argsort(myList) #converts list to NumPy internally
>>> timeit(lambda: [myList[i] for i in so])
12.29590070003178

>>> myArray = np.random.rand(100)
>>> so = np.argsort(myArray)
>>> timeit(lambda: myArray[so]) 
0.42915570305194706

是的,首先将其转换为数组可能是一个选项,但这是我想避免的。无论如何,感谢您的回答;我已经点赞了它。 - Cleb
@goncalopp 我认为列表推导式是在for循环下涵盖的。 - rohanp
@Cleb 使用NumPy方法比列表推导式快大约28倍。为什么你想要避免使用它?
timeit(lambda: [l[i] for i in o]) 12.29590070003178
timeit(lambda: a[o]) 0.42915570305194706
- rohanp
@Cleb 如果你最终使用了这个方法,为了达到这个速度,我还需要改变另一件事情:so = np.argsort(myList) 会在内部将列表转换为numpy数组。反复转换两次效率低下,因此我保留了一个单独的变量myArray。 - rohanp
1
@rohanp:timeit(lambda: a[o])是什么?既没有定义'a'也没有定义'o'。这应该是'myArray'和'so'吗? - Cleb
显示剩余2条评论

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