I have an Structured array like this:
a = np.array([(0. , 1. , 2.) , (10. , 11. , 12. )] ,
dtype=[(\'PositionX\', \'
In [206]: a
Out[206]:
array([( 0., 1., 2.), ( 10., 11., 12.)],
dtype=[('PositionX', '<f8'), ('PositionY', '<f8'), ('PositionZ', '<f8')])
A record is a compound numpy dtype object, that is displayed as a tuple.
In [207]: type(a[0])
Out[207]: numpy.void
In [208]: a[0].dtype
Out[208]: dtype([('PositionX', '<f8'), ('PositionY', '<f8'), ('PositionZ', '<f8')])
Fields ('columns') of the array are arrays, and do the normal array math.
In [209]: a['PositionX']
Out[209]: array([ 0., 10.])
In [210]: a['PositionX']+a['PositionY']
Out[210]: array([ 1., 21.])
But math has not been defined for the compound dtype:
In [211]: a[0]+a[1]
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype([('PositionX', '<f8'), ('PositionY', '<f8'), ('PositionZ', '<f8')]) ....
If you allow me to convert the whole array to 2d, I can add rows:
In [213]: a1=np.array(a.tolist())
In [214]: a1
Out[214]:
array([[ 0., 1., 2.],
[ 10., 11., 12.]])
In [215]: a1[0]+a1[1]
Out[215]: array([ 10., 12., 14.])
There are other ways of converting a structured array to 2d (with view
or astype
) but this tolist()
is easiest to use and most consistent. More on this at https://stackoverflow.com/a/43380941/901925
But to do math with individual records you have to convert them to arrays or treat them like the displayed tuples.
In [218]: np.array(a[0].tolist())
Out[218]: array([ 0., 1., 2.])
In [219]: np.array(a[0].tolist())+np.array(a[1].tolist())
Out[219]: array([ 10., 12., 14.])
But are you happy with this array, or do you want that back in the a.dtype
?
In [234]: np.array(tuple(asum), a.dtype)
Out[234]:
array(( 10., 12., 14.),
dtype=[('PositionX', '<f8'), ('PositionY', '<f8'), ('PositionZ', '<f8')])
The data to a structured array must be in tuples or list of tuples.
You have to do the same dtype
conversion if you use the zipped approach that @Mohamed Lakhal
showed
In [236]: [i+j for i,j in zip(a[0],a[1])]
Out[236]: [10.0, 12.0, 14.0]
In [237]: np.array(tuple([i+j for i,j in zip(a[0],a[1])]), a.dtype)
While a view
approach as Divakar commented converts the whole array:
In [227]: a.view('<f8')
Out[227]: array([ 0., 1., 2., 10., 11., 12.])
In [228]: a.view('<f8').reshape(-1,3)
Out[228]:
array([[ 0., 1., 2.],
[ 10., 11., 12.]])
it does not work with a record:
In [229]: a[0].view('<f8')
....
ValueError: new type not compatible with array.
This is a better converter to 2d array:
In [239]: a.view('3f8')
Out[239]:
array([[ 0., 1., 2.],
[ 10., 11., 12.]])
In [240]: a[0].view('3f8')
Out[240]: array([ 0., 1., 2.])
In [241]: a[[0,1]].view('3f8')
Out[241]:
array([[ 0., 1., 2.],
[ 10., 11., 12.]])
In [242]: a[[0,1]].view('3f8').sum(axis=0)
Out[242]: array([ 10., 12., 14.])
You're getting an error just because the a[i] are tuples, you can't add directly tuple. You have to access them, a more pythonic way to achieve this would be:
map(sum, zip(*a))
the zip function do exactly what you're looking for, after that you have to process each entry according to what you need, in your case sum
, you can also try this:
result = []
for elem in zip(*a):
result.append(sum(elem))