如何“压缩排序”并行numpy数组?

2024-06-08 08:07:30 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我有两个平行列表,并希望按第一个列表中元素的顺序对它们进行排序,这非常简单:

>>> a = [2, 3, 1]
>>> b = [4, 6, 7]
>>> a, b = zip(*sorted(zip(a,b)))
>>> print a
(1, 2, 3)
>>> print b
(7, 4, 6)

如果不将numpy数组解压到传统的Python列表中,我如何使用numpy数组进行相同的操作呢?


Tags: numpy元素列表排序顺序数组传统zip
3条回答

就像@Peter Hansen的答案一样,在对数组进行排序之前,这会生成数组的副本。但它很简单,主排序在适当的位置,使用第二个数组进行辅助排序,而且应该非常快:

a = np.array([2, 3, 1])
b = np.array([4, 6, 2])
# combine, sort and break apart
a, b = np.sort(np.array([a, b]))

更新:正如注释中指出的,上面的代码实际上不起作用。下面是一些更好的代码。这应该是相当有效的—例如,它避免显式地生成数组的额外副本。很难说它有多有效,因为the documentation没有给出任何关于numpy.lexsort算法的细节。但它应该可以很好地工作,因为这正是lexsort为之编写的作业。

a = np.array([5, 3, 1])
b = np.array([4, 6, 7])
new_order = np.lexsort([b, a])
a = a[new_order]
b = b[new_order]
print(a, b)
# (array([1, 3, 5]), array([7, 6, 4]))

这是一种不创建中间Python列表的方法,尽管它确实需要一个NumPy“记录数组”来用于排序。如果您的两个输入数组实际上是相关的(如电子表格中的列),那么这可能是处理数据的一种有利方式,而不是始终保留两个不同的数组,在这种情况下,您已经有了一个记录数组,而您最初的问题只需在数组上调用sort()就可以得到解决。

在将两个数组打包到一个记录数组中之后,执行in-place sort

>>> from numpy import array, rec
>>> a = array([2, 3, 1])
>>> b = array([4, 6, 7])
>>> c = rec.fromarrays([a, b])
>>> c.sort()
>>> c.f1   # fromarrays adds field names beginning with f0 automatically
array([7, 4, 6])

已编辑若要使用rec.fromarrays()以简化操作,请跳过多余的数据类型,使用默认排序键,使用默认字段名而不是指定(基于this example)。

b[a.argsort()]应该能做到。

这就是它的工作原理。首先,您需要找到一个排序排列。argsort是一个计算此值的方法:

>>> a = numpy.array([2, 3, 1])
>>> p = a.argsort()
>>> p
[2, 0, 1]

您可以很容易地检查这是否正确:

>>> a[p]
array([1, 2, 3])

现在对b应用相同的置换

>>> b = numpy.array([4, 6, 7])
>>> b[p]
array([7, 4, 6])

相关问题 更多 >