我有一个确定元素排序的数组:
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数组是否有类似的“关键函数”概念?
答案 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])
-
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)]