Reputation: 33
Having an array filled with zeros, I want to create a view, use .ravel() on it, modify the array returned by ravel() and have this modification change the original array. Without the use of ravel() it works fine
zeros = np.zeros(shape=(10,10))
view = zeros[3:7,3:7]
view[:] = 1
print(zeros)
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
[0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
[0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
[0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
However, using .ravel() creates the following:
zeros = np.zeros(shape=(10,10))
view = zeros[3:7,3:7].ravel()
view[:] =1
print(zeros)
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
As one would expect, view.flags["OWNDATA"] returns "True", so a copy has been created. How can I change the code to create a view that lets me modify the original array ?
Tried
view[:] = view[:]+1
Upvotes: 1
Views: 81
Reputation: 231385
You can't. ravel
, which is just a reshape
, sometimes has to make a copy. A view is possible only when the selection of values can be expressed in a regular pattern, using either scalar or slice indices.
Consider a small example with distinct values:
In [47]: x = np.arange(9).reshape(3,3).copy()
In [48]: x
Out[48]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [49]: x.base
In [50]: y = x[1:,1:]
In [51]: y
Out[51]:
array([[4, 5],
[7, 8]])
In [52]: y.base
Out[52]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [53]: z = y.ravel()
In [54]: z
Out[54]: array([4, 5, 7, 8])
In [55]: x.ravel()
Out[55]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])
In [56]: z.base
y
is a view
, but z
is not. There's no way of selecting the z
values from the flat x
values with a slice.
But you can use the flat
iterator to index y
in a flat manner:
In [59]: y.flat[2]=10
In [60]: y
Out[60]:
array([[ 4, 5],
[10, 8]])
In [61]: x
Out[61]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 10, 8]])
Upvotes: 1