关于python:Numpy在另一个数组中查找元素索引

Numpy finding element index in another array

我有一个具有唯一正整数的数组/集合,即

1
>>> unique = np.unique(np.random.choice(100, 4, replace=False))

以及包含从上一个数组中采样的多个元素的数组,例如

1
>>> A = np.random.choice(unique, 100)

我想把数组A的值映射到这些值在unique中出现的位置。

到目前为止,我找到的最佳解决方案是通过一个映射数组:

1
2
>>> table = np.zeros(unique.max()+1, unique.dtype)
>>> table[unique] = np.arange(unique.size)

上面为每个元素分配了数组上的索引,因此可以稍后通过高级索引来映射A

1
2
3
4
5
6
>>> table[A]
array([2, 2, 3, 3, 3, 3, 1, 1, 1, 0, 2, 0, 1, 0, 2, 1, 0, 0, 2, 3, 0, 0, 0,
       0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 3, 0, 1, 3, 0, 1, 2, 3, 3, 3, 3, 1,
       3, 0, 1, 2, 0, 0, 2, 3, 1, 0, 3, 2, 3, 3, 3, 1, 1, 2, 0, 0, 2, 0, 2,
       3, 1, 1, 3, 3, 2, 1, 2, 0, 2, 1, 0, 1, 2, 0, 2, 0, 1, 3, 0, 2, 0, 1,
       3, 2, 2, 1, 3, 0, 3, 3], dtype=int32)

这已经给了我正确的解决方案。但是,如果unique中的唯一数字非常稀疏和大,则此方法意味着创建一个非常大的table数组,以便存储一些数字以便以后进行映射。

有更好的解决办法吗?

注:Aunique都是样本数组,不是实数数组。所以问题不在于如何生成位置索引,而在于如何有效地将A的元素映射到unique的索引,我想在numpy中加速的伪代码如下:

1
2
3
B = np.zeros_like(A)
for i in range(A.size):
    B[i] = unique.index(A[i])

(假设unique是上述伪代码中的列表)。


unique密度相当大时,您问题中描述的表方法是最佳选择,但unique.searchsorted(A)应产生相同的结果,并且不要求unique密度。searchsorted对于ints很好,如果有人试图用有精度限制的浮点来做这种事情,可以考虑这样的事情。


numpy_索引包(免责声明:我是其作者)包含一个与list.index等价的矢量化包,它不需要与max元素成比例的内存,但只与输入本身成比例:

1
2
import numpy_indexed as npi
npi.indices(unique, A)

请注意,它也适用于任意数据类型和维度。另外,所查询的数组不需要是唯一的;将返回遇到的第一个索引,与for list相同。


您可以将标准的python dictnp.vectorize一起使用。

1
2
inds = {e:i for i, e in enumerate(unique)}
B = np.vectorize(inds.get)(A)