将二进制字符串转换为NumPy数组

34

假设我有以下字符串:

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

这里我获得它的来源并不重要,但是为了让事情具体化,假设我是从一个二进制文件中读取的。

我知道我的字符串是四个浮点数(每个浮点数占用4个字节)的二进制表示。我想将这些浮点数作为numpy数组获取。我可以这样做:

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

但是创建一个中间元组似乎很繁琐。 有没有一种方法可以在不创建中间元组的情况下执行此操作?

编辑

我还想以这样的方式构建数组,以便我可以指定字符串的字节序。


可能是重复的问题:如何从字符串创建一个numpy数组? - Aurelius
@aurelius 我想说这个问题很接近,但并不完全是重复的。虽然答案相似,但这个问题是关于浮点数,那个问题是关于整数的。 - Uyghur Lives Matter
2个回答

49
>>> 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)

或者,如果你想要大端序:

>>> 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)

在Python 3之前,显然不需要使用b

实际上,如果您真的正在使用二进制文件来加载数据,则甚至可以跳过使用字符串的步骤,并使用numpy.fromfile()直接从文件中加载数据。

另外,为了参考dtype,请查看:http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html


这太棒了(谢谢)。我能看到这里的一个缺点是没有办法指定字节序。你有什么想法吗? - mgilson
在dtype中指定字节序。np.dtype('<f4')表示小端字节序(虽然这是默认值,但除了代码清晰度外没有必要),np.dtype('>f4')表示大端字节序。因此,np.fromstring(b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@', dtype=np.dtype('>f4'))的结果为array([4.60060299e-41, 8.96831017e-44, 2.30485571e-41, 4.60074312e-41], dtype=float32)。参考:http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html - JAB
完美。正是我所寻找的。 - mgilson
我认为你应该在回答中加上关于字节序转换的内容。我认为这对于其他有同样疑问的人也可能有帮助,因此将其突出显示比在评论中更合理。 - mgilson
@JAB - +1。一个注意点是,我认为小端序不是默认设置。相反,机器类型是默认设置。因此,如果您在大端序的机器上(这些日子很少见)读取小端序字符串,则需要指定'<f4'。 - mtrw
哦,这是一个很好的观点。那我稍微修改一下我的答案。 - JAB

0

np.fromstring()已被弃用,请使用np.frombuffer()代替。

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.]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接