给出一个起始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]
低效的交换方法将遍历s1
和s2
,如下所示:
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
循环的情况下就地执行此操作?
答案 0 :(得分: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])
答案 1 :(得分: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
的某些加速。对于这些1D问题,take / put只是更快。