简体   繁体   中英

Does Numpy fancy indexing copy values directly to another array?

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 .

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)

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM