1

给定一个如下所示的起始 numpy 数组:

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

当有重复时,将一组值交换为另一组值的最有效方法是什么?例如,让

s1 = [1,2,4]
s2 = [4,1,2]

一个低效的交换方法会迭代s1s2因此:

B2 = B.copy()
for x,y in zip(s1,s2):
    B2[B==x] = y

作为输出给予

B2 -> [4, 4, 4, 0, 1, 1, 4, 3, 3, 0, 2, 2, 2, 2]

zip有没有办法在没有循环的情况下基本上就地执行此操作?

4

2 回答 2

2
>>> B = np.array( [1, 1, 1, 0, 2, 2, 1, 3, 3, 0, 4, 4, 4, 4] )
>>> s1 = [1,2,4]
>>> s2 = [4,1,2]
>>> B2 = B.copy()
>>> c, d = np.where(B == np.array(s1)[:,np.newaxis])
>>> B2[d] = np.repeat(s2,np.bincount(c))
>>> B2
array([4, 4, 4, 0, 1, 1, 4, 3, 3, 0, 2, 2, 2, 2])
于 2012-08-22T15:26:03.340 回答
1

如果您只有介于 0 和 n 之间的整数(如果没有问题,可以推广到任何整数范围,除非它非常稀疏),最有效的方法是使用 take/fancy 索引:

swap = np.arange(B.max() + 1) # all values in B
swap[s1] = s2 # replace the values you want to be replaced

B2 = swap.take(B) # or swap[B]

对于此处给出的小 B,这似乎几乎是两倍快,但是对于较大的 B,将 B 重复到大约 100000 的长度已经得到了 8 倍的加速。这也避免了每个 s1 元素的 == 操作,因此随着 s1/s2 变大,可以更好地扩展。

编辑:您也可以使用 np.put (也在另一个答案中)为swap[s1] = s2. 对于这些一维问题,取/放的速度更快。

于 2012-08-22T15:58:55.477 回答