How to populate an existing numpy array with specific dtype

后端 未结 2 1147
有刺的猬
有刺的猬 2021-01-25 02:23

Let\'s say that I have this initial numpy array with some fixed dtype:

array = numpy.array([(1, \'a\'), (2, \'b\')],
                    numpy.dtype([(\'idfield\         


        
相关标签:
2条回答
  • 2021-01-25 02:51

    Like @juanpa.arrivillaga commented, it's cleaner to define your dtype only once:

    array_dt = np.dtype([
        ('idfield', np.int32),
        ('textfield', '|S256')
    ])
    

    Then define your second list of values as an array and then concatenate

    array2 = np.array(value, array_dt)                                     
    array = np.concatenate([array, array2])
    
    0 讨论(0)
  • 2021-01-25 03:14

    np.append is a simple cover to np.concatenate

    def append(arr, values, axis=None):
        arr = asanyarray(arr)
        if axis is None:
            if arr.ndim != 1:
                arr = arr.ravel()
            values = ravel(values)
            axis = arr.ndim-1
        return concatenate((arr, values), axis=axis)
    
    In [89]: dt = np.dtype('U5,int')
    In [90]: arr = np.array([('one',1)], dtype=dt)
    In [91]: np.append(arr, ('two',2))
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-91-bc17d9ad4a77> in <module>()
    ----> 1 np.append(arr, ('two',2))
     ...
    -> 5166     return concatenate((arr, values), axis=axis)
    
    TypeError: invalid type promotion
    

    In this case it does

    In [92]: np.ravel(('two',2))
    Out[92]: array(['two', '2'], dtype='<U3')
    

    turning the tuple into a 2 element string dtype array. Now concatenate tries to join an array of dt with the U3 array, and it can't. There's nothing in the append uses the arr.dtype as the basis for turning values into an array. You need to do that yourself. numpy can only do so much to infer you intentions. :)

    So if you specify common the dtype it works:

    In [93]: np.append(arr, np.array(('two',2),dt))
    Out[93]: array([('one', 1), ('two', 2)], dtype=[('f0', '<U5'), ('f1', '<i4')])
    

    I dislike append because new users often misuse it. Usually they think of it as a list append clone, which it is not.

    But it does have one advantage - it promotes the dimensions of 0d inputs:

    In [94]: np.concatenate([arr, np.array(('two',2),dt)])
    ...
    ValueError: all the input arrays must have same number of dimensions
    

    Making the 2nd array 1d works:

    In [95]: np.concatenate([arr, np.array([('two',2)],dt)])
    Out[95]: array([('one', 1), ('two', 2)], dtype=[('f0', '<U5'), ('f1', '<i4')])
    

    append hides the dimensional adjustment that concatenate needs.

    But where possible it is better to create a list of arrays (or tuples) and do concatenate just once:

    In [96]: alist = [('one',1),('two',2),('three',3)]
    In [97]: ll = [np.array([x],dt) for x in alist]
    In [98]: ll
    Out[98]: 
    [array([('one', 1)], dtype=[('f0', '<U5'), ('f1', '<i4')]),
     array([('two', 2)], dtype=[('f0', '<U5'), ('f1', '<i4')]),
     array([('three', 3)], dtype=[('f0', '<U5'), ('f1', '<i4')])]
    
    In [100]: np.concatenate(ll)
    Out[100]: 
    array([('one', 1), ('two', 2), ('three', 3)],
          dtype=[('f0', '<U5'), ('f1', '<i4')])
    

    But making the array directly from a list of tuples is even better:

    In [101]: np.array(alist, dt)
    Out[101]: 
    array([('one', 1), ('two', 2), ('three', 3)],
          dtype=[('f0', '<U5'), ('f1', '<i4')])
    
    0 讨论(0)
提交回复
热议问题