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

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

6 Comments

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?
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
perfect. just what I was looking for.
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.
@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'.
|
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.]

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.