Jan Strube wrote:
> I'm having a difficult time understanding the following behavior:
>> import numpy as N
> # create a new array 4 rows, 3 columns
> x = N.random.random((4, 3))
> # elementwise multiplication
> x*x
>> newtype = N.dtype([('x', N.float64), ('y', N.float64), ('z', N.float64)])
>> # interpret the array as an array of cartesian coordinates
> x.dtype = newtype
>> x*x
>> --> TypeError: unsupported operand type(s) for *: ' numpy.ndarray' and
> 'numpy.ndarray'
>> N.__version__
> '1.0.2.dev3498'
>> So just by assigning names to the columns, I can't multiply the arrays
> any more?
No, it's not a bug. It's a "missing feature"." You have created a
"record-array". All of the ufuncs are undefined for arrays with fields
(what is sometimes called a variable item-size array). They are
undefined for two reasons
1) It's not clear how to define them. It is ambiguous in general. For
this specific case, it is probably clear what you want, but what do you
want for the general case data-type with fields defined. This has
never been thought out clearly.
2) It's not trivial to implement. Basically, handling the general case
would require some alterations to the main ufunc code loops in order to
pass information about the size of the array element that is presently
not available.
Perhaps some day we will be able to add element-by-element ufuncs for
record arrays that will basically recurse through the fields, but that
will require some coding effort that is not on my radar for the next while.
What you can do, is maintain a view of the data as a 4x3 array of floats
and do the multiplication with that array. The same memory can then
also be viewed as a length 4 1-d array of coordinates if you like.
You can also be more explicit about what you want to do with each column
by writing
y = x.copy()
y['x'] = x['x']*x['x']
y['y'] = x['y']*x['y']
y['z'] = x['z']*x['z']
>> Please tell me this is a bug ;-)
Sorry, it's not that easy.
-Travis