34

Assume I have the string:

my_data = '\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@'

Where I got it is irrelevant, but for the sake of having something concrete, assume I read it from a binary file.

I know my string is the binary representation of 4 (4-byte) floats. I would like to get those floats as a numpy array. I could do:

import struct
import numpy as np
tple = struct.unpack( '4f', my_data )
my_array = np.array( tple, dtype=np.float32 )

But it seems silly to create an intermediate tuple. Is there a way to do this operation without creating an intermediate tuple?

EDIT

I would also like to be able to construct the array in such a way that I can specify the endianness of the string.

2
  • possible duplicate of How do I create a numpy array from string? Commented Feb 6, 2015 at 18:02
  • @Aurelius I would say this is close, but not an exact duplicate. Though the answers are similar, this question is about floats and that question is about integers. Commented Feb 6, 2015 at 19:29

2 Answers 2

51
>>> np.frombuffer(b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@', dtype='<f4') # or dtype=np.dtype('<f4'), or np.float32 on a little-endian system (which most computers are these days)
array([ 1.,  2.,  3.,  4.], dtype=float32)

Or, if you want big-endian:

>>> np.frombuffer(b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@', dtype='>f4') # or dtype=np.dtype('>f4'), or np.float32  on a big-endian system
array([  4.60060299e-41,   8.96831017e-44,   2.30485571e-41,
         4.60074312e-41], dtype=float32)

The b isn't necessary prior to Python 3, of course.

In fact, if you actually are using a binary file to load the data from, you could even skip the using-a-string step and load the data directly from the file with numpy.fromfile().

Also, dtype reference, just in case: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html

6
  • This is excellent. (thanks). One downside here that I can see is that there's no way to specify endianness. Any ideas on that one? Commented Aug 1, 2012 at 13:23
  • Specify the endianness in the dtype. np.dtype('<f4') for little-endian (though this is the default, so isn't necessary for anything other than code clarity), np.dtype('>f4') for big-endian. So np.fromstring(b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@', dtype=np.dtype('>f4')) results in array([4.60060299e-41, 8.96831017e-44, 2.30485571e-41, 4.60074312e-41], dtype=float32). Reference: docs.scipy.org/doc/numpy/reference/arrays.dtypes.html Commented Aug 1, 2012 at 13:25
  • perfect. just what I was looking for. Commented Aug 1, 2012 at 13:26
  • I think you should add the stuff about endianness conversion to your answer. I think that could also be potentially helpful to someone else with the same question I had so it makes sense to feature it more prominently than in a comment. Commented Aug 1, 2012 at 13:37
  • @JAB - +1. One note - I don't think little-endian is the default. Rather, machine type is the default. So if you're on a big endian machine (rare these days) and are reading a little endian string, you need to specify '<f4'. Commented Aug 1, 2012 at 13:44
0

np.fromstring() is deprecated. Use np.frombuffer() instead.

import numpy as np

my_data = b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@'

# np.fromstring is deprecated
# data = np.fromstring(my_data, np.float32)
data = np.frombuffer(my_data, np.float32)

print(data)
[1. 2. 3. 4.]

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.