Replace elements in numpy array avoiding loops

• A+
Category：Languages

I have a quite large 1d numpy array Xold with given values. These values shall be replaced according to the rule specified by a 2d numpy array Y: An example would be

Xold=np.array([0,1,2,3,4]) Y=np.array([[0,0],[1,100],[3,300],[4,400],[2,200]])

Whenever a value in Xold is identical to a value in Y[:,0], the new value in Xnew should be the corresponding value in Y[:,1]. This is accomplished by two nested for loops:

Xnew=np.zeros(len(Xold)) for i in range(len(Xold)): for j in range(len(Y)):     if Xold[i]==Y[j,0]:         Xnew[i]=Y[j,1]

With the given example, this yields Xnew=[0,100,200,300,400]. However, for large data sets this procedure is quite slow. What is a faster and more elegant way to accomplish this task?

We can use np.searchsorted for a generic case when the data in first column of Y is not necessarily sorted -

sidx = Y[:,0].argsort() out = Y[sidx[np.searchsorted(Y[:,0], Xold, sorter=sidx)],1]

Sample run -

In : Xold Out: array([14, 10, 12, 13, 11])  In : Y Out:  array([[ 10,   0],        [ 11, 100],        [ 13, 300],        [ 14, 400],        [ 12, 200]])  In : sidx = Y[:,0].argsort()     ...: out = Y[sidx[np.searchsorted(Y[:,0], Xold, sorter=sidx)],1]  In : out Out: array([400,   0, 200, 300, 100])

If not all elements have corresponding mappings available, then we need to do a bit more of work, like so -

sidx = Y[:,0].argsort() sorted_indx = np.searchsorted(Y[:,0], Xold, sorter=sidx) sorted_indx[sorted_indx==len(sidx)] = len(sidx)-1 idx_out = sidx[sorted_indx] out = Y[idx_out,1] out[Y[idx_out,0]!=Xold] = 0 # NA values as 0s