6

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.

1

1 Answer 1

10

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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())
@GivenX did you use your code to convert to numpy arrays or did u just use df.to_records()?
I just used df.to_records()

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.