[Numpy-discussion] views or copy
josef.pktd@gmai...
josef.pktd@gmai...
Tue Apr 7 11:07:36 CDT 2009
On Mon, Apr 6, 2009 at 11:34 PM, Robert Kern <robert.kern@gmail.com> wrote:
> On Mon, Apr 6, 2009 at 22:31, <josef.pktd@gmail.com> wrote:
>> I ran again into a problem where numpy created a view (which I didn't
>> realize) and an operation works differently on the view than if it
>> were a copy.
>>
>> I try to construct an example array, which, however, is only a view
>>
>>>>> x,y = np.mgrid[0:3,0:3]
>>>>> xx = np.vstack((x.flatten(), y.flatten(), np.ones(9))).T
>>>>> xx
>> array([[ 0., 0., 1.],
>> [ 0., 1., 1.],
>> [ 0., 2., 1.],
>> [ 1., 0., 1.],
>> [ 1., 1., 1.],
>> [ 1., 2., 1.],
>> [ 2., 0., 1.],
>> [ 2., 1., 1.],
>> [ 2., 2., 1.]])
>>>>> xx.flags
>> C_CONTIGUOUS : False
>> F_CONTIGUOUS : True
>> OWNDATA : False
>> WRITEABLE : True
>> ALIGNED : True
>> UPDATEIFCOPY : False
>>>>> xx.base
>> array([[ 0., 0., 0., 1., 1., 1., 2., 2., 2.],
>> [ 0., 1., 2., 0., 1., 2., 0., 1., 2.],
>> [ 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
>>>>> xx == xx.base
>> False
>>
>> When I convert it to a view as a structured array, it produces a
>> strange result. I didn't get what I thought I should get
>>
>>>>> xx.view([('',xx.dtype)]*xx.shape[1])
>> array([[(0.0, 0.0, 0.0), (0.0, 1.0, 2.0), (1.0, 1.0, 1.0)],
>> [(1.0, 1.0, 1.0), (0.0, 1.0, 2.0), (1.0, 1.0, 1.0)],
>> [(2.0, 2.0, 2.0), (0.0, 1.0, 2.0), (1.0, 1.0, 1.0)]],
>> dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8')])
>>
>> if I make a copy and then construct a view as structured array, I get
>> what I want
>>
>>>>> xx2 = xx.copy()
>>>>> xx2.view([('',xx2.dtype)]*xx2.shape[1])
>> array([[(0.0, 0.0, 1.0)],
>> [(0.0, 1.0, 1.0)],
>> [(0.0, 2.0, 1.0)],
>> [(1.0, 0.0, 1.0)],
>> [(1.0, 1.0, 1.0)],
>> [(1.0, 2.0, 1.0)],
>> [(2.0, 0.0, 1.0)],
>> [(2.0, 1.0, 1.0)],
>> [(2.0, 2.0, 1.0)]],
>> dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8')])
>>
>> Are there rules for this behavior or a description in the docs,
>> because my mistakes in this are quite difficult to debug? Or do I have
>> to make a copy by default as in matlab?
>
> .view() makes a view onto the memory, not onto the
> memory-as-if-it-were-normalized-to-C-contiguous-order. Use
> ascontiguous() if you need to ensure the latter.
>
I guess that's np.ascontiguousarray(xx)
Thanks, I'm still trying to get the trickier parts of numpy.
I was trying this out some more in order to understand the view
examples. In my other examples, numpy raises an exception of the array
is not c-contiguous when constructing a view, see below.
Shouldn't numpy raise an exception also for my original example, since
also there the array wasn't c-contiguous instead of silently using the
array base?
At least it would reduce debugging time, since I am not used to having
to think about memory layout when I just do some array and matrix
calculations and the arrays are not what they appear to be. (coming
from other, more restrictive matrix languages like matlab or gauss).
Related to my original problem, is there a way to convert between
structured arrays and plain ndarrays (in both directions) that forces
a copy instead of just creating a view?
Josef
Josef
>>> import numpy as np
>>> xx = np.array([[ 0., 0., 1.],
... [ 0., 1., 1.],
... [ 0., 2., 1.],
... [ 1., 0., 1.],
... [ 1., 1., 1.],
... [ 1., 2., 1.],
... [ 2., 0., 1.],
... [ 2., 1., 1.]])
>>> xx.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> xx.view([('',float),('',float),('',float)])
array([[(0.0, 0.0, 1.0)],
[(0.0, 1.0, 1.0)],
[(0.0, 2.0, 1.0)],
[(1.0, 0.0, 1.0)],
[(1.0, 1.0, 1.0)],
[(1.0, 2.0, 1.0)],
[(2.0, 0.0, 1.0)],
[(2.0, 1.0, 1.0)]],
dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8')])
>>> xx[:6,:].flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> xx[:6,:].view([('',float),('',float),('',float)])
array([[(0.0, 0.0, 1.0)],
[(0.0, 1.0, 1.0)],
[(0.0, 2.0, 1.0)],
[(1.0, 0.0, 1.0)],
[(1.0, 1.0, 1.0)],
[(1.0, 2.0, 1.0)]],
dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8')])
but the following raise exceptions as desired
>>> xx[:,:2].flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> xx[:,:2].view([('',float),('',float)])
Traceback (most recent call last):
File "<pyshell#326>", line 1, in <module>
xx[:,:2].view([('',float),('',float)])
ValueError: new type not compatible with array.
>>> xx.T[:,:2].view([('',float),('',float)])
Traceback (most recent call last):
File "<pyshell#327>", line 1, in <module>
xx.T[:,:2].view([('',float),('',float)])
ValueError: new type not compatible with array.
>>> xx.T[:,:2].flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
the following also produces a view on the base, not the one that I
expected, and no exception is raised
xx.reshape(-1,2,order='F').view([('',float),('',float)])
More information about the Numpy-discussion
mailing list