6

My goal is to assign the values of an existing 2D array, or create a new array, using two 2D arrays of the same shape, one with values and one with indices to assign the corresponding value to.

X = np.array([range(5),range(5)])
X
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])

Y= np.array([range(5), [2,3,4,1,0]])
Y
array([[0, 1, 2, 3, 4],
       [2, 3, 4, 1, 0]])

My desired output is an array of the same shape as X and Y, with the values of X given in the index from the corresponding row in Y. This result can be achieved by looping through each row in the following way:

output = np.zeros(X.shape)

for i in range(X.shape[0]):
    output[i][Y[i]] = X[i]
output 
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 4.,  3.,  0.,  1.,  2.]])

Is there a more efficient way to apply this sort of assignment?

np.take(output, Y) 

Will return the items in the output array I would like to assign to the values of X to, but I believe np.take does not produce a reference to the original array, and instead a new array.

1

1 Answer 1

7
for i in range(X.shape[0]):
    output[i][Y[i]] = X[i]

is equivalent to

I = np.arange(X.shape[0])[:, np.newaxis]
output[I, Y] = X

For example,

X = np.array([range(5),range(5)])
Y = np.array([range(5), [2,3,4,1,0]])
output = np.zeros(X.shape)
I = np.arange(X.shape[0])[:, np.newaxis]
output[I, Y] = X

yields

>>> output
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 4.,  3.,  0.,  1.,  2.]])

There is not much difference in performance when the loop has few iterations. But if X.shape[0] is large, then using indexing is much faster:

def using_loop(X, Y):
    output = np.zeros(X.shape)
    for i in range(X.shape[0]):
        output[i][Y[i]] = X[i]
    return output

def using_indexing(X, Y):
    output = np.zeros(X.shape)
    I = np.arange(X.shape[0])[:, np.newaxis]
    output[I, Y] = X
    return output

X2 = np.tile(X, (100,1))
Y2 = np.tile(Y, (100,1))

In [77]: %timeit using_loop(X2, Y2)
1000 loops, best of 3: 376 µs per loop

In [78]: %timeit using_indexing(X2, Y2)
100000 loops, best of 3: 15.2 µs per loop
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.