numpy数组之间的交叉引用

6

我有一个包含id的1维数组,例如:

a = [1, 3, 4, 7, 9]

接下来是另一个二维数组:

b = [[1, 4, 7, 9], [3, 7, 9, 1]]

我希望有一个与b形状相同的第三个数组,其中每个项都是来自a的对应项的索引,即:
c = [[0, 2, 3, 4], [1, 3, 4, 0]]

使用numpy的向量化方式可以完成这个任务吗?

3
np.searchsorted(a, b),如果我理解正确的话,a 需要被排序。lu = np.empty(max(a)+1, a.dtype); lu[a] = np.arange(len(a)); lu[np.array(b)] 对于更大的数组来说应该会更快,但需要额外的空间用于查找数组。 - Michael Szczesny
3个回答

2

这可能听起来不太合理,但是...你可以使用np.interp来实现这个功能...

a = [1, 3, 4, 7, 9]
sorting = np.argsort(a)
positions = np.arange(0,len(a))
xp = np.array(a)[sorting]
fp = positions[sorting]
b = [[1, 4, 7, 9], [3, 7, 9, 1]]
c = np.rint(np.interp(b,xp,fp)) # rint is better than astype(int) because floats are tricky.
# but astype(int) should work faster for small len(a) but not recommended.

只要len(a)小于浮点数所能表示的最大整数(16777217),这个应该可以工作.....而且这个算法的速度是O(n * log(n)),或者更准确地说是len(b)*log(len(a))。

1

实际上,这个解决方案只有一行代码。唯一的问题是在执行这一行代码之前,需要对数组进行重新整形,并在执行完成后再将其还原回去:

import numpy as np

a = np.array([1, 3, 4, 7, 9])
b = np.array([[1, 4, 7, 9], [3, 7, 9, 1]])
original_shape = b.shape

c = np.where(b.reshape(b.size, 1) == a)[1]

c = c.reshape(original_shape)

这将导致:
[[0 2 3 4]
 [1 3 4 0]]

0

广播来拯救!

>>> ((np.arange(1, len(a) + 1)[:, None, None]) * (a[:, None, None] == b)).sum(axis=0) - 1
array([[0, 2, 3, 4],
       [1, 3, 4, 0]])

3
虽然这个解决方案很简单,但对于大型数组来说非常低效。它的运行时间为二次函数 O(len(a) * len(b)),并需要二次数量的内存。因此,计算一个大小为 100,000 的数组将在大多数计算机上崩溃。MichaelSzczesny 的解决方案具有(准)线性时间复杂度,并且使用更少的内存。 - Jérôme Richard
哈,好吧。至少开发过程很有趣 :) - user17242583
1
不仅如@JérômeRichard所说,这种方法在内存效率上也存在问题。我认为,即使您的代码非常优雅,对于大型数组来说,这些数学运算也会变得非常昂贵。当使用Kronecker乘积(使用np.kron)来增加矩阵的维度时,也会出现类似的问题,而不是使用np.repmat - econbernardo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接