scanny
scanny

Reputation: 28903

Which numpy operations copy and which mutate?

Is there a general rule of thumb for knowing which operations on a numpy.ndarray produce a copy of the values and which mutate them in-place?

I'm pretty new to numpy and I'm sure I'll learn the hard way eventually, but I was wondering if there were general principles driving mutability that might help speed my learning.

Upvotes: 4

Views: 1009

Answers (1)

tel
tel

Reputation: 13999

Functions that mutate in place

Relatively few numpy functions mutate in place. For the most part, numpy functions return array views when they can, and copies when they can't.

Here's an exhaustive list (trawled from the docs) of functions/methods that mutate in place:

  • ndarray.resize
  • ndarray.sort
  • All of the in-place binary operators (eg +=, *=, ^=, etc)
  • numpy.fill_diagonal
  • numpy.random.shuffle
  • ndarray.partition

and here's a list of the functions/methods that can optionally mutate in place:

  • ndarray.byteswap
  • numpy.nan_to_num

Certain assignments will also mutate an array in place. You can change the values in an array by assigning to a slice (eg arr[...] = 1 will set every value in an array to 1), and you can reshape an array by assigning a new shape directly to .shape, eg arr.shape = (2,3) (won't always work, see notes here).

There's also some functions that support an out keyword arg. These functions will behave as mutators if you pass the same array as both input and out.

Fair warning, I may have missed one or two mutators that weren't clearly marked in the docs. In any case, the list is short, so there's not much to memorize.

Notes on view vs copy return values

One of the goals of the numpy devs over the last few years seemingly has been to make it more common for the numpy functions and the ndarray methods to return views instead of copies. At this point, it's reasonably safe to assume that if a numpy function/method can return a view, it will do so by default.

For example, ndarray.flatten and ndarray.ravel do the same thing (returned a flattened array). However, the docs for ndarray.flatten explicitly say that it will return a copy, whereas the docs for ndarray.ravel say that it will return a copy only if absolutely necessary.

In live code, as a rule of thumb you can always check if an operation produced a view or a copy by comparing the id of the .base of your result to the id of original array. For example:

arr = np.array([[1, 2],
                [3, 4],
                [5, 6]])

arrflat = arr.flatten()
assert arrflat.base is not arr

arrravel = arr.ravel()
assert arrravel.base is arr

Upvotes: 7

Related Questions