I would like to randomly swap one 0
and one 1
in a one dimensional array which contain only 0 and 1 many many times say up to N = 10^6
. Here is my code for doing the swap one time.
import numpy as np
# a contains only 0 and 1
a = np.array([0,1,1,0,1,1,0,0,0,1])
# j1 random position of 0, j2 random position of 1
j1 = np.random.choice(np.where(a==0)[0])
j2 = np.random.choice(np.where(a==1)[0])
# swap
a[j1], a[j2] = a[j2], a[j1]
Since I would like to do this process many many time, at every iteration, I need to use np.where() to locate posistions of 0 and 1, which I think is not that efficient.
Is there any other approach which can be more effecient ?
CodePudding user response:
You could maintain the result of the where
expressions yourself, as swaps are executed, so that you don't need to re-execute that where
call. You'd only do it once, at the start of the procedure, but then in the loop, you'd incrementally adjust.
Also, the swap can be replaced by two assignments, since you know that the 0 will become 1 and vice versa.
a = np.array([0,1,1,0,1,1,0,0,0,1])
# One-time preprocessing
zeroes = np.where(a==0)[0]
ones = np.where(a==1)[0]
# In a loop:
j0 = np.random.choice(zeroes)
j1 = np.random.choice(ones)
# get the chosen indices:
i0 = zeroes[j0]
i1 = ones[j1]
# Keep the two collections in sync with the swap that now happens
zeroes[j0] = i1
ones[j1] = i0
# The swap itself
a[i0] = 1
a[i1] = 0
Note that the length of zeroes
and ones
doesn't change: we can just reuse the two slots that were selected at every swap.
CodePudding user response:
a[j1], a[j2] = a[j2], a[j1]
isn't a safe array swap
a[[j1,j2]] = a[[j2,j1]]
is better