python - How to randomly change positions of non-zero entries of an array where certain rows are excluded -
i have numpy array consisting of lot of 0s , few non-zero entries e.g. (just toy example):
myarray = np.array([[ 0. , 0. , 0.79], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0.435 , 0. ]])
now move each of non-zero entries given probability means of entries moved, might remain @ current position. of rows not allowed contain non-zero entry means values not allowed moved there. implemented follows:
import numpy np # reproducibility np.random.seed(2) myarray = np.array([[ 0. , 0. , 0.79], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0.435 , 0. ]]) # list of rows numbers not allowed moved ignorerows = [2] # moving probability probmove = 0.3 # non-zero entries nzentries = np.nonzero(myarray) # indices of non-zero entries tuples indnz = zip(nzentries[0], nzentries[1]) # store values valnz = [myarray[i] in indnz] # generating probabilities moving each non-zero entry lprob = np.random.rand(len(nzentries)) allowedrows = [ind ind in xrange(myarray.shape[0]) if ind not in ignorerows] # replace "range" in python 3.x allowedcols = [ind ind in xrange(myarray.shape[1])] # replace "range" in python 3.x indprob, prob in enumerate(lprob): # move probability if prob <= probmove: # randomly change position myarray[np.random.choice(allowedrows), np.random.choice(allowedcols)] = valnz[indprob] # set old position 0 myarray[indnz[indprob]] = 0. print myarray
first, determine indices , values of non-zero entries. assign probability each of these entries determines whether entry moved. allowed target rows.
in second step, loop through list of indices , move them according moving probability done choosing allowed rows , columns, assigning respective value these new indices , set "old" value 0.
it works fine code above, however, speed matters in case , wonder whether there more efficient way of doing this.
edit: hpaulj's answer helped me rid of for-loop nice , reason why accepted answer. incorporated comments , posted answer below well, in case else stumbles on example , wonders how used answer in end.
you can index elements arrays, so:
valnz=myarray[nzentries]
can replace zip
, comprehension.
simplify these 2 assignments:
allowedcols=np.arange(myarray.shape[1]); allowedrows=np.delete(np.arange(myarray.shape[0]), ignorerows)
with:
i=lprob<probmove; valnz=valnz[i];indnz=indnz[i]
you don't need perform prog<probmove
test each time in loop; iterate on valnz
, indnz
.
i think random.choice
can generated of these valnz
@ once:
np.random.choice(np.arange(10), 10, true) # 10 choices range replacement
with should possible move of points without loop.
i haven't worked out details yet.
there 1 way in iterative move different parallel one. if destination choice value, iterative approach can on write, , possibly move given value couple of times. parallel code not perform sequential moves. have decide whether 1 correct or not.
there ufunc
method, .at
, performs unbuffered operations. works operations add
, don't know if apply indexing move this.
simplified version of iterative moving:
in [106]: arr=np.arange(20).reshape(4,5) in [107]: i=np.nonzero(arr>10) in [108]: v=arr[i] in [109]: rows,cols=np.arange(4),np.arange(5) in [110]: in range(len(v)): dest=(np.random.choice(rows),np.random.choice(cols)) arr[dest]=v[i] arr[i[0][i],i[1][i]] = 0 in [111]: arr out[111]: array([[ 0, 18, 2, 14, 11], [ 5, 16, 7, 13, 19], [10, 0, 0, 0, 0], [ 0, 17, 0, 0, 0]])
possible vectorized version:
in [117]: dest=(np.random.choice(rows,len(v),true),np.random.choice(cols,len(v),true)) in [118]: dest out[118]: (array([1, 1, 3, 1, 3, 2, 3, 0, 0]), array([3, 0, 0, 1, 2, 3, 4, 0, 1])) in [119]: arr[dest] out[119]: array([ 8, 5, 15, 6, 17, 13, 19, 0, 1]) in [120]: arr[i]=0 in [121]: arr[dest]=v in [122]: arr out[122]: array([[18, 19, 2, 3, 4], [12, 14, 7, 11, 9], [10, 0, 0, 16, 0], [13, 0, 15, 0, 17]])
if sets 0
after, there more zeros.
in [124]: arr[dest]=v in [125]: arr[i]=0 in [126]: arr out[126]: array([[18, 19, 2, 3, 4], [12, 14, 7, 11, 9], [10, 0, 0, 0, 0], [ 0, 0, 0, 0, 0]])
same dest
, done iteratively:
in [129]: in range(len(v)): .....: arr[dest[0][i],dest[1][i]] = v[i] .....: arr[i[0][i],i[1][i]] = 0 in [130]: arr out[130]: array([[18, 19, 2, 3, 4], [12, 14, 7, 11, 9], [10, 0, 0, 16, 0], [ 0, 0, 0, 0, 0]])
with small size, , high moving density, differences between iterative , vectorized solutions large. sparse array fewer.
Comments
Post a Comment