Converting pandas dataframe to numpy array with headers and dtypes

14,991

Use df.to_records() to convert your dataframe to a structured array.

You can pass index=False to remove index from your result.

import numpy as np

df = pd.DataFrame(np.random.rand(10,3),columns=['Acol','Ccol','Bcol'])

res = df.to_records(index=False)

# rec.array([(0.12448699852020828, 0.7621451848466592, 0.0958529943831431),
#  (0.14534869167076214, 0.695297214355628, 0.3753874117495527),
#  (0.09890006207909052, 0.46364777245941025, 0.10216301104094272),
#  (0.3467673672203968, 0.4264108141950761, 0.1475998692158026),
#  (0.9272619907467186, 0.3116253419608288, 0.5681628329642517),
#  (0.34509767424461246, 0.5533523959180552, 0.02145207648054681),
#  (0.7982313824847291, 0.563383955627413, 0.35286630304880684),
#  (0.9574060540226251, 0.21296949881671157, 0.8882413119348652),
#  (0.0892793829627454, 0.6157843461905468, 0.8310360916075473),
#  (0.4691016244437851, 0.7007146447236033, 0.6672404967622088)], 
#           dtype=[('Acol', '<f8'), ('Ccol', '<f8'), ('Bcol', '<f8')])

A structured array will always have one dimension. That can't be changed.

But you can get the shape via:

res.view(np.float64).reshape(len(res), -1).shape  # (10, 3)

For performance, if you are manipulating data, you are better off using numpy.array via df.to_numpy() and recording your column names in a dictionary with integer keys.

Share:
14,991
GivenX
Author by

GivenX

Updated on June 17, 2022

Comments

  • GivenX
    GivenX almost 2 years

    I have been trying to convert a pandas dataframe into a numpy array, carrying over the dtypes and header names for ease of reference. I need to do this as the processing on pandas is WAY too slow, numpy is 10 fold quicker. I have this code from SO that gives me what I need apart from that the result does not look like a standard numpy array - i.e. it does not show the columns numbers in the shape.

    [In]:
    df = pd.DataFrame(randn(10,3),columns=['Acol','Ccol','Bcol'])
    arr_ip = [tuple(i) for i in df.as_matrix()]
    dtyp = np.dtype(list(zip(df.dtypes.index, df.dtypes)))
    dfnp= np.array(arr_ip, dtype=dtyp)
    print(dfnp.shape)
    dfnp
    
    [Out]: 
    
    (10,) #expecting (10,3)
    
    array([(-1.0645345 ,  0.34590193,  0.15063829),
    ( 1.5010928 ,  0.63312454,  2.38309797),
    (-0.10203999, -0.40589525,  0.63262773),
    ( 0.92725915,  1.07961763,  0.60425353),
    ( 0.18905164, -0.90602597, -0.27692396),
    (-0.48671514,  0.14182815, -0.64240004),
    ( 0.05012859, -0.01969079, -0.74910076),
    ( 0.71681329, -0.38473052, -0.57692395),
    ( 0.60363249, -0.0169229 , -0.16330232),
    ( 0.04078263,  0.55943898, -0.05783683)],
    dtype=[('Acol', '<f8'), ('Ccol', '<f8'), ('Bcol', '<f8')])
    

    Am I missing something or is there another way of doing this? I have many df's to convert and their dtypes and column names vary so I need this automated approach. I also need it to be efficient due to the large number of df's.

  • GivenX
    GivenX about 6 years
    Thanks, that is perfect. I did have to do a ravel to get it back into a pandas dataframe after the heavy lifting processing was done in numpy: res_pd = pd.DataFrame(res.ravel())
  • redwolf_cr7
    redwolf_cr7 almost 6 years
    @GivenX did you use your code to convert to numpy arrays or did u just use df.to_records()?
  • GivenX
    GivenX almost 6 years
    I just used df.to_records()