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.

asked Aug 1, 2012 at 13:14
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

mgilson
312k70 gold badges657 silver badges723 bronze badges
answered Aug 1, 2012 at 13:19
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.]
answered Dec 5, 2020 at 23:38

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.