另一个订购一个numpy数组

时间:2018-06-08 22:27:46

标签: python arrays sorting numpy

我有一个确定元素排序的数组:

order = [3, 1, 4, 2]

然后我想要排序另一个更大的数组(只包含那些元素):

a = np.array([4, 2, 1, 1, 4, 3, 1, 3])    

使得order中首先出现的元素在结果中排​​在第一位,等等 在直接的Python中,我会用一个关键函数来做到这一点:

sorted(a, key=order.index)
[3, 3, 1, 1, 1, 4, 4, 2]

我怎样才能(有效地)使用numpy? numpy数组是否有类似的“关键函数”概念?

3 个答案:

答案 0 :(得分:5)

具体案例:Xrm.WebApi.execute

对于Ints,我们可以使用bincount -

ints

示例运行 -

np.repeat(order,np.bincount(a)[order])

通用案例

方法#1

使用In [146]: sorted(a, key=order.index) Out[146]: [3, 3, 1, 1, 1, 4, 4, 2] In [147]: np.repeat(order,np.bincount(a)[order]) Out[147]: array([3, 3, 1, 1, 1, 4, 4, 2]) -

对所有dtypes进行推广
bincount

方法#2-A

# https://stackoverflow.com/a/41242285/ @Andras Deak def argsort_unique(idx): n = idx.size sidx = np.empty(n,dtype=int) sidx[idx] = np.arange(n) return sidx sidx = np.argsort(order) c = np.bincount(np.searchsorted(order,a,sorter=sidx)) out = np.repeat(order, c[argsort_unique(sidx)]) np.unique来自searchsorted的所有元素都位于order -

a

方法#2-B

为了涵盖所有情况,我们需要一个额外的步骤 -

unq, count = np.unique(a, return_counts=True)
out = np.repeat(order, count[np.searchsorted(unq, order)])

答案 1 :(得分:1)

在@Divakar的解决方案的基础上,您可以计算每个元素出现的次数,然后多次重复有序元素:

c = Counter(a)
np.repeat(order, [c[v] for v in order])

(如果您愿意,可以对计数查找进行矢量化)。我喜欢这个,因为它是线性时间,即使它不是纯粹的numpy。

我猜一个纯粹的numpy等价物看起来像这样:

count = np.unique(a, return_counts=True)[1]
np.repeat(order, count[np.argsort(np.argsort(order))])

但这不是直接的,更多的代码,以及太多种类。 :)

答案 2 :(得分:0)

这是将纯Python方法直接转换为numpy。关键的想法是用排序向量中的查找替换order.index函数。不确定这是否比你提出的解决方案更简单或更快,但它可能会推广到其他一些案例。

import numpy as np
order = np.array([3, 1, 4, 2])
a = np.array([4, 2, 1, 1, 4, 3, 1, 3])  

# create sorted lookup vectors
ord = np.argsort(order)
order_sorted = order[ord]
indices_sorted = np.arange(len(order))[ord]

# lookup the index in `order` for each value in the `a` vector
a_indices = np.interp(a, order_sorted, indices_sorted).astype(int)

# sort `a` using the retrieved index values
a_sorted = a[np.argsort(a_indices)]
a_sorted

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

这是一种更直接的方式(基于this question),但它似乎比np.interp方法慢约4倍:

lookup_dict = dict(zip(order, range(len(order))))
indices = np.vectorize(lookup_dict.__getitem__)(a)
a_sorted = a[np.argsort(indices)]