在屏蔽数组中形成项目索引,在原始排序数组中计算同一项目的索引 mask-> idx按升序:排序的随机项目-> idx按升序: idx以任何顺序-> idx以升序

问题描述

我使用下面的方法(遵循提出的解决方here掩盖了排序的一维numpy数组):

def get_from_sorted(sorted,idx):
     mask = np.zeros(sorted.shape,bool)
     mask[idx] = True
     return sorted[mask]

在对索引idx进行屏蔽之后,python方法返回该数组。例如,如果sorted = {np.array([0.1,0.2,0.3.0.4,0.5])和idx = {np.array([4,1]),则方法get_from_sorted应该返回np.array([0.1,0.5])(注意保留了原始数组中的顺序。)

问题:我需要获得掩蔽后数组中各项的索引与原始列表中各项之间的映射。在上面的示例中,这样的映射是

0 -> 0
1 -> 1
2 -> 5

因为0.1、0.2和0.5在sorted中分别位于第0,第1和第5位。

如何有效地对此映射进行编程?

对效率的要求:效率是解决问题的关键。在此,“ idx”和“ sorted”都是100万个元素的一维数组,idx是大约50万个元素的一维数组(取自图像处理应用程序)。因此,在我的情况下,例如,使用np.where相对于原始数组一一检查或以矢量化方式检查蒙版数组的元素,效果不佳。理想情况下,在掩码数组和原始排序数组中的索引之间应该存在一个相对简单的数学关系。有想法吗?

解决方法

(从您的示例中)我假设原始列表是排序列表。在这种情况下,除非我误解,否则您只需执行以下操作即可:

idx.sort()

,然后映射为i-> idx[i]

当然,如果idx的原始顺序很重要,请先进行复制。

,

对我来说,一个问题不清楚。它可以有几种解释。

mask-> idx(按升序):

让我尝试使用这个非常大的数据集(1000万个值,其中10%是True):

x = np.random.choice(a=[False,True],size=(10000000,),p=[0.9,0.1])

在这种情况下,使用np.where非常有效:

%timeit np.where(x)[0]
%timeit x.nonzero()[0]
%timeit np.arange(len(x))[x]
24.8 ms ± 551 µs per loop (mean ± std. dev. of 7 runs,10 loops each)
24.5 ms ± 229 µs per loop (mean ± std. dev. of 7 runs,10 loops each)
52.4 ms ± 895 µs per loop (mean ± std. dev. of 7 runs,10 loops each)

排序的随机项目-> idx(按升序):

如果您对需要从sorted中取出的物品的位置没有任何参考,那么如果没有重复的物品,您仍然可以找到idx。这是O(n logn)

x = np.random.choice(a=[False,0.1])
arr = np.linspace(0,1,len(x))
sub_arr = arr[x] %input data: skipping 90% of items

%timeit np.searchsorted(arr,sub_arr) %output data
112 ms ± 2.2 ms per loop (mean ± std. dev. of 7 runs,10 loops each) 

idx(以任何顺序)-> idx(以升序)

这很简单:

x = np.arange(10000000)
np.random.shuffle(x)
idx = x[:1000000] #input data: first 1M of random idx
%timeit np.sort(idx) #output data
65.3 ms ± 316 µs per loop (mean ± std. dev. of 7 runs,10 loops each)