ravel
is returning a copy, not a view
From the numpy.ravel
docs:
A 1-D array, containing the elements of the input, is returned. A copy is made only if needed.
So basically, when ravelling the transpose, a copy is in fact needed. You're changing the value in a copy, so that's not reflected in the original array.
Testing whether a returned array is a view or a copy
For a simple case like this, you can test whether an array b
is or is not a view of a
by comparing the identity of b.base
and a
:
a = np.array([[1,2,3], [4,5,6]])
b = a.T
c = b.ravel()
print('b is a view of a\n%s\n' % (b.base is a))
print('c is a view of a\n%s\n' % (c.base is a))
Output:
b is a view of a
True
c is a view of a
False
Why does a.T.ravel()
return a copy?
Shocker: there actually is a way to make a.T.ravel()
return a view instead of a copy. You can do so by explicitly setting order='F'
(ie Fortran order):
a = np.array([[1,2,3], [4,5,6]])
c = a.T.ravel()
d = a.T.ravel(order='F')
print('d is a view of a\n%s\n' % (d.base is a))
Output:
d is a view of a
True
However, changing the value of the order
kwarg will change the order (fancy that) of the values in the raveled array:
print('c\n%s\n' % c)
print('d\n%s\n' % d)
Output:
c
[1 4 2 5 3 6]
d
[1 2 3 4 5 6]
In order to understand why a change in the order
leads to a view being returned, we can look at the code of the ravel
function itself. The implementation of np.ndarray.ravel
is buried in the C layer. Reading over the source for that, it's clear that in order to return a view from ravel
, two conditions must be met:
The kwarg has a default value of order='C'
. Thus, by default ravel
will only return a view if you run it on a C-contiguous array. Most of the time when you initialize a fresh Numpy array a
, it will start off as C-contiguous. However, the transpose a.T
will be F-contiguous. You can see this in action in your code by checking the .flags
property of your arrays:
a = np.array([[1,2,3], [4,5,6]])
print('the flags of a\n%s\n' % a.flags)
print('the flags of a.T\n%s\n' % a.T.flags)
Output:
the flags of a
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
the flags of a.T
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
What the heck do C- and F-contiguous mean?
There's a good chance that the terms C-contiguous and F-contiguous seem like gibberish to you. Explaining them would require a whole other question, which happily someone on SO has already asked. Here's a link to an old answer that gives a really intuitive overview of what C and F order actually mean.
Caveat
In your actual code, I wouldn't worry too much about whether ravel
is return views or copies. In reality, you don't always get a performance boost by ensuring the use of views. Avoid premature optimization in general.