2

My attempts to create structured arrays are failing:

I create an array shape (4,5)

sample = np.array([[0.01627555, 1.55885081, 1.99043222, 0.00898849, 1.43987417],
       [0.01875182, 0.97853587, 2.09924081, 0.00474326, 1.31002428],
       [0.01905054, 1.74849054, 1.78033106, 0.01303594, 1.28518933],
       [0.01753927, 1.22486495, 1.88287677, 0.01823483, 1.36472148]])

assign dtype for each of the five columns:

sample.dtype = [('X', 'f4'), ('Y', 'f4'), ('Z', 'f4'), ('f', 'f4'), ('g', 'f4' )]

I would expect:

sample['X']
> array([0.01627555, 0.01875182, 0.01905054, 0.01753927], dtype=float32)

However, what I'm doing gives

array([[-1.6328180e-12,  1.9988040e+00],
       [ 7.9082486e+13,  2.0124049e+00],
       [ 7.7365790e-24,  1.9725413e+00],
       [ 3.6306835e+36,  1.9853595e+00]], dtype=float32)

I know how to do this in pandas, etc, but I need the structured array in this occasion. What am I doing wrong?

2 Answers 2

2

You have to reformat your array with np.core.records.array to a list of tuples to convert it as recarray

dtype = [('X', 'f4'), ('Y', 'f4'), ('Z', 'f4'), ('f', 'f4'), ('g', 'f4' )]

arr = np.core.records.array(tuple(sample.T), dtype=dtype)

Output:

>>> arr  # note the recarray
rec.array([(0.01627555, 1.5588508, 1.9904323, 0.00898849, 1.4398742),
           (0.01875182, 0.9785359, 2.0992408, 0.00474326, 1.3100243),
           (0.01905054, 1.7484906, 1.780331 , 0.01303594, 1.2851893),
           (0.01753927, 1.224865 , 1.8828768, 0.01823483, 1.3647215)],
          dtype=[('X', '<f4'), ('Y', '<f4'), ('Z', '<f4'), ('f', '<f4'), ('g', '<f4')])

>>> arr['X']  # note you still have ndarray
array([0.01627555, 0.01875182, 0.01905054, 0.01753927], dtype=float32)
Sign up to request clarification or add additional context in comments.

Comments

1

The main structured array documentation page introduces recfunctions:

https://numpy.org/doc/stable/user/basics.rec.html#module-numpy.lib.recfunctions

In [2]: import numpy.lib.recfunctions as rf

Define the dtype object:

In [11]: dt = np.dtype([('X', 'f4'), ('Y', 'f4'), ('Z', 'f4'), ('f', 'f4'), ('g', 'f4' )])                              

rf has a function designed to perform this kind of conversion:

In [13]: arr = rf.unstructured_to_structured(sample, dtype=dt)                                                          
In [14]: arr                                                                                                            
Out[14]:                                                                                                                
    array([(0.01627555, 1.5588508, 1.9904323, 0.00898849, 1.4398742),                                                              
    (0.01875182, 0.9785359, 2.0992408, 0.00474326, 1.3100243),                                                              
    (0.01905054, 1.7484906, 1.780331 , 0.01303594, 1.2851893),                                                              
    (0.01753927, 1.224865 , 1.8828768, 0.01823483, 1.3647215)],                                                            
    dtype=[('X', '<f4'), ('Y', '<f4'), ('Z', '<f4'), ('f', '<f4'), ('g', '<f4')])                                     

You can also create a structured array with a list of tuples, which will look a lot like the above displays of the array.

 In [16]: np.array([tuple(x) for x in sample], dtype=dt)   

The other answer uses a records function to make the array from a list of arrays, one per field:

 np.core.records.fromarrays(list(sample.T), dtype=dt)                                                              

Like many rf functions, this function creates a "blank" array with the desired dtype and shape, and copies values to it by field name:

In [31]: dt.names                                                                                                       
Out[31]: ('X', 'Y', 'Z', 'f', 'g')                                                                                      
In [32]: res = np.zeros(4, dtype=dt)                                                                                    
In [33]: for i,name in enumerate(dt.names):                                                                                 
    ...:     res[name] = sample[:,i] 

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.