numpy Structured array adding record

后端 未结 2 514
闹比i
闹比i 2021-01-29 03:46

I have an Structured array like this:

a = np.array([(0. , 1. , 2.) , (10. , 11. , 12. )] ,
             dtype=[(\'PositionX\', \'

        
相关标签:
2条回答
  • 2021-01-29 04:15
    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.])
    
    0 讨论(0)
  • 2021-01-29 04:30

    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))
    
    0 讨论(0)
提交回复
热议问题