Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell if NumPy creates a view or a copy?

Tags:

python

copy

numpy

For a minimal working example, let's digitize a 2D array. numpy.digitize requires a 1D array:

import numpy as np N = 200 A = np.random.random((N, N)) X = np.linspace(0, 1, 20) print np.digitize(A.ravel(), X).reshape((N, N)) 

Now the documentation says:

... A copy is made only if needed.

How do I know if the ravel copy it is "needed" in this case? In general - is there a way I can determine if a particular operation creates a copy or a view?

like image 380
Hooked Avatar asked Jul 17 '12 14:07

Hooked


People also ask

What is the difference between copy and view in NumPy?

The main difference between a copy and a view of an array is that the copy is a new array, and the view is just a view of the original array. The copy owns the data and any changes made to the copy will not affect original array, and any changes made to the original array will not affect the copy.

Does NumPy array make a copy?

Slicing an array does not make a copy, it just creates a new view on the existing array's data.

What are views in NumPy?

NumPy has ndarray. view() method which is a new array object that looks at the same data of the original array. Unlike the earlier case, change in dimensions of the new array doesn't change dimensions of the original.

Does NumPy indexing create copy?

Boolean indexing returns a copy of the data, not a view of the original data, like one gets for slices. I can manipulate b and data is preserved. However, as you've identified, assignments made via indexed arrays are always made to the original data.


2 Answers

This question is very similar to a question that I asked a while back:

You can check the base attribute.

a = np.arange(50) b = a.reshape((5, 10)) print (b.base is a) 

However, that's not perfect. You can also check to see if they share memory using np.may_share_memory.

print (np.may_share_memory(a, b)) 

There's also the flags attribute that you can check:

print (b.flags['OWNDATA'])  #False -- apparently this is a view e = np.ravel(b[:, 2]) print (e.flags['OWNDATA'])  #True -- Apparently this is a new numpy object. 

But this last one seems a little fishy to me, although I can't quite put my finger on why...

like image 188
mgilson Avatar answered Nov 16 '22 00:11

mgilson


In the documentation for reshape there is some information about how to ensure an exception if a view cannot be made:

It is not always possible to change the shape of an array without copying the data. If you want an error to be raised if the data is copied, you should assign the new shape to the shape attribute of the array:

>>> a = np.zeros((10, 2)) # A transpose make the array non-contiguous >>> b = a.T # Taking a view makes it possible to modify the shape without modiying the # initial object. >>> c = b.view() >>> c.shape = (20) AttributeError: incompatible shape for a non-contiguous array 



This is not exactly an answer to your question, but in certain cases it may be just as useful.

like image 39
amicitas Avatar answered Nov 15 '22 23:11

amicitas