0

I have an Structured array like this:

a = np.array([(0. , 1. , 2.) , (10. , 11. , 12. )] ,
             dtype=[('PositionX', '<f8'), ('PositionY', '<f8'), ('PositionZ', '<f8')])

Now, I want add record 0 (a[0]) and record 1 (a[1]), to get something like : (10. , 12. , 14. )

When I write something like :

a[0] + a[1]

I got error which tell me you cant add two dtype object or something like that.

So, I think maybe I can turn a[0] to be a regular vector, then perform adding.

But numpy.array(a[0]) have same dtype as a[0], and numpy.array(a[0],dtype=np.float64) does not work too.

So, can anyone tell me how to convert a[0] to regular vector? please don't tell me to covert structured array to regular array. because I just want take few of my array record and do adding. Besides, I really want to know how to turn an object like a[0] to an regular vector.

1

2 Answers 2

1

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))
Sign up to request clarification or add additional context in comments.

2 Comments

Ok, you mean take every tuple and make an list in python, well, i can do that. but can we finish this in numpy? dose numpy have some way to turn an dtype with something like a[0] to an normal 1d array?
if you're trying to convert a tuple to a list, the function list is what you're looking for.
0
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.])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.