2

According to the documentation that I could find, when using fancy indexing a copy rather than a view is returned. However, I couldn't figure out what its behavior is during assignment to another array, for instance:

A = np.arange(0,10)
B = np.arange(-10,0)
fancy_slice = np.array([0,3,5])
A[fancy_slice] = B[fancy_slice]

I understand that A will just receive a call to __setitem__ while B will get a call to __getitem__. What I am concerned about is whether an intermediate array is created before copying the values over to A.

2 Answers 2

3

The interpreter will parse the code and issue the method calls as:

A[idx] = B[idx]

A.__setitem__(idx, B.__getitem__(idx))

The B method is evaluated fully before being passed to the A method. numpy doesn't alter the Python interpreter or its syntax. Rather it just adds functions, objects, and methods.

Functionally, it should be the equivalent to

temp = B[idx]
A[idx] = temp
del temp

We could do some timeit just be sure.

In [712]: A = np.zeros(10000,int)
In [713]: B = np.arange(10000)
In [714]: idx = np.arange(0,10000,100)
In [715]: timeit A[idx] = B[idx]
1.2 µs ± 3.24 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [716]: %%timeit
     ...: temp = B[idx]
     ...: A[idx] = temp
     ...: 
1.11 µs ± 0.669 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

There are some alternative functions/methods, like add.at, copyto, place, put, that may do some copies without an intermediate, but I haven't used them much. This indexed assignment is good enough - most of the time.

Example with copyto

In [718]: wh = np.zeros(A.shape, bool)
In [719]: wh[idx] = True
In [721]: np.copyto(A, B, where=wh)
In [722]: timeit np.copyto(A, B, where=wh)
7.47 µs ± 9.92 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

So even without timing the construction of the boolean mask, copyto is slower.

put and take are no better:

In [727]: timeit np.put(A,idx, np.take(B,idx))
7.98 µs ± 8.34 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Sign up to request clarification or add additional context in comments.

Comments

1

An intermediate array is created. It has to be created. NumPy doesn't see

A[fancy_slice] = B[fancy_slice]

It sees

                 B[fancy_slice]

on its own, with no idea what the context is. This operation is defined to make a new array, and NumPy makes a new array.

Then, NumPy sees

A[fancy_slice] = <the array created by the previous operation>

and copies the data into A.

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.