如何从字节创建一个numpy的ndarray?
如何从字节创建一个numpy的ndarray?
我可以使用myndarray.tobytes()
将numpy的ndarray转换为字节。那么如何将其转换回ndarray呢?
使用.tobytes()
方法文档中的示例:
>>> x = np.array([[0, 1], [2, 3]]) >>> bytes = x.tobytes() >>> bytes b'\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00' >>> np.some_magic_function_here(bytes) array([[0, 1], [2, 3]])
问题的出现原因是用户想要将字节数据转换为numpy的ndarray对象。解决方法有两种。
第一种方法是如果用户在转换之前已经知道了ndarray对象的维度,可以使用以下代码进行转换:
import numpy x = numpy.array([[1.0,1.1,1.2,1.3],[2.0,2.1,2.2,2.3],[3.0,3.1,3.2,3.3]],numpy.float64) xBytes = x.tobytes() newX = numpy.ndarray((3,4),numpy.float64,xBytes)
第二种方法是如果用户的数据以字节记录的形式存储,而不是作为整个ndarray对象,并且每个ndarray对象的选择的数据都不同,可以将预先准备好的数据作为字节存储在python的bytearray中,然后在达到所需的大小时,以bytearray作为缓冲区提供所需的维度和数据类型。
以上就是问题的原因和解决方法。
如何从字节创建一个numpy ndarray?
要反序列化字节,您需要使用np.frombuffer()
函数。tobytes()
函数将数组序列化为字节,而np.frombuffer()
函数将其反序列化。请注意,一旦序列化,形状信息就会丢失,这意味着在反序列化之后,需要将其重新reshape回原始形状。
下面是一个完整的示例:
import numpy as np x = np.array([[0, 1], [2, 3]], np.int8) bytes = x.tobytes() # bytes 是一个原始数组,不包含有关 x 形状的信息 # 让我们确保:我们有4个值,数据类型为 int8(每个数组项占用一个字节),因此 bytes 的长度应为 4 个字节 assert len(bytes) == 4, "Ha??? Weird machine..." deserialized_bytes = np.frombuffer(bytes, dtype=np.int8) deserialized_x = np.reshape(deserialized_bytes, newshape=(2, 2)) assert np.array_equal(x, deserialized_x), "Deserialization failed..."
以上是解决该问题的方法。通过使用np.frombuffer()
函数从字节中反序列化数组,并使用np.reshape()
函数将其恢复到原始形状,可以实现从字节创建numpy ndarray的目的。
如何从字节中创建一个numpy ndarray?
在编辑之后,看起来你走错了方向!当只需要从这些字节中重建数组时,你不能使用np.tobytes()来存储包含所有信息(如形状和类型)的完整数组!它只会保存原始数据(单元格值)并按照C或Fortran顺序展开这些数据。
现在我们不知道你的任务是什么。但是你将需要基于序列化的方法。有很多方法可以实现,其中最简单的是使用Python的pickle(以下是一个示例,适用于Python 3):
import pickle import numpy as np x = np.array([[0, 1], [2, 3]]) print(x) x_as_bytes = pickle.dumps(x) print(x_as_bytes) print(type(x_as_bytes)) y = pickle.loads(x_as_bytes) print(y)
输出结果:
[[0 1] [2 3]] b'\x80\x03cnumpy.core.multiarray\n_reconstruct\nq\x00cnumpy\nndarray\nq\x01K\x00\x85q\x02C\x01bq\x03\x87q\x04Rq\x05(K\x01K\x02K\x02\x86q\x06cnumpy\ndtype\nq\x07X\x02\x00\x00\x00i8q\x08K\x00K\x01\x87q\tRq\n(K\x03X\x01\x00\x00\x00<q\x0bNNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00tq\x0cb\x89C \x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00q\rtq\x0eb.'[[0 1] [2 3]]
更好的选择是joblib的pickle,它对大型数组进行了专门的拾取。joblib的函数基于文件对象,也可以使用字节字符串在内存中使用,使用Python的BytesIO。
参考链接:
- [joblib](https://pythonhosted.org/joblib/)
- [BytesIO](https://docs.python.org/3/library/io.html#binary-i-o)