【问题标题】:Convert a numpy.ndarray to string(or bytes) and convert it back to numpy.ndarray将 numpy.ndarray 转换为字符串(或字节)并将其转换回 numpy.ndarray
【发布时间】:2015-07-21 22:47:32
【问题描述】:

这里有点麻烦,

我正在尝试将 numpy.ndarray 转换为字符串,我已经这样做了:

randomArray.tostring()

它有效,但我想知道是否可以将其转换回 numpy.ndarray。

最好的方法是什么?

我正在使用 numpy 1.8.1

上下文: 目标是将 numpy.ndarray 作为消息发送到 rabbitmq(pika 库)

【问题讨论】:

标签: python numpy multidimensional-array


【解决方案1】:

您可以为此使用fromstring() 方法:

arr = np.array([1, 2, 3, 4, 5, 6])
ts = arr.tostring()
print(np.fromstring(ts, dtype=int))

>>> [1 2 3 4 5 6]

对不起,简短的回答,没有足够的评论点。请记住说明数据类型,否则您将陷入痛苦的世界。

注意 fromstring 从 numpy 1.14 开始

sep : str,可选

数据中分隔数字的字符串;元素之间的多余空格也会被忽略。

自 1.14 版起已弃用:传递默认值 sep='' 已弃用,因为它会触发此函数的弃用二进制模式。此模式将字符串解释为二进制字节,而不是带有十进制数字的 ASCII 文本,这种操作最好拼写为 frombuffer(string, dtype, count)。如果 string 包含 unicode 文本,则 fromstring 的二进制模式将首先使用 utf-8 (python 3) 或默认编码 (python 2) 将其编码为字节,这两者都不会产生正常的结果。

【讨论】:

  • 我不知道fromstring,很好!但是,它似乎不适用于多维数组(返回多维数组的flat 版本)。如果你知道尺寸,我想你可以在之后重塑数组。
  • 这可能有效,奇怪的是我的tostring() 方法返回了奇怪的东西(字节?)fromstring() 不能正常工作。
  • @Ampo 您可以使用 repr(ts) 查看二进制文件,但您必须使用 np.fromstring(ts,dtype=int) 进行转换,记住使用正确的数据类型。您使用的是浮点数还是整数?发布您尝试发送的数组类型。
  • 坦率地说,我不会用 numpy 进行序列化,我的建议是将大量转储到 JSON 中并在另一端解析它......不用头疼。
  • np.fromstring() 已弃用,请改用np.frombuffer()
【解决方案2】:

如果你使用tostring,你会丢失关于形状和数据类型的信息:

>>> import numpy as np
>>> a = np.arange(12).reshape(3, 4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> s = a.tostring()
>>> aa = np.fromstring(a)
>>> aa
array([  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
         1.48219694e-323,   1.97626258e-323,   2.47032823e-323,
         2.96439388e-323,   3.45845952e-323,   3.95252517e-323,
         4.44659081e-323,   4.94065646e-323,   5.43472210e-323])
>>> aa = np.fromstring(a, dtype=int)
>>> aa
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> aa = np.fromstring(a, dtype=int).reshape(3, 4)
>>> aa
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

这意味着您必须将元数据连同数据一起发送给收件人。要交换自动一致的对象,请尝试 cPickle:

>>> import cPickle
>>> s = cPickle.dumps(a)
>>> cPickle.loads(s)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

【讨论】:

  • dtype 重要:np.uint8 / np.uint16
【解决方案3】:

假设您有一个 numpy 整数数组(它适用于其他类型,但您需要稍作修改)。你可以这样做:

a = np.array([0, 3, 5])
a_str = ','.join(str(x) for x in a) # '0,3,5'
a2 = np.array([int(x) for x in a_str.split(',')]) # np.array([0, 3, 5])

如果您有一个浮点数组,请务必在最后一行将int 替换为float

您也可以使用__repr__() 方法,这将有利于多维数组:

from numpy import array
numpy.set_printoptions(threshold=numpy.nan)
a = array([[0,3,5],[2,3,4]])
a_str = a.__repr__() # 'array([[0, 3, 5],\n       [2, 3, 4]])'
a2 = eval(a_str) # array([[0, 3, 5],
                 #        [2, 3, 4]])

【讨论】:

  • 由于我使用 3D 阵列(图像),__repr__() 方法应该可以工作,但它没有。该数组非常大(其中包含 1000000+ 个值)我在使用 __repr__()eval() 转换后得到 1000 个值 crash(?)
  • @Ampo 是的,由于大型 numpy 数组的表示(大型数组有 ... 而不是完整数组),因此 __repr__() 会在更大的数组中崩溃。您可以更改该行为(使用 set_printoptions)...我刚刚编辑了我的答案,看看是否效果更好。
  • 将 import numpy 添加到您的第二个代码可能会有所帮助,因为它会为不知道的人提供错误 (numpy.set_printoptions)。
【解决方案4】:

我知道,我迟到了,但这是正确的做法。使用 base64。此技术会将数组转换为字符串。

import base64
import numpy as np
random_array = np.random.randn(32,32)
string_repr = base64.binascii.b2a_base64(random_array).decode("ascii")
array = np.frombuffer(base64.binascii.a2b_base64(string_repr.encode("ascii"))) 
array = array.reshape(32,32)

数组转字符串

将二进制数据转换为base64编码的一行ASCII字符,解码为ASCII得到字符串repr。

字符串转数组

首先,将字符串编码为 ASCII 格式,然后 将一块base64数据转回二进制,并返回二进制数据。

【讨论】:

  • 这行得通。我唯一需要添加的就是在最后做 reshape(32,32)
【解决方案5】:

这是对ajsp 使用 XML-RPC 的回答的稍微即兴的回答。

在服务器端转换数据时,使用 '.tostring()' 方法。这会将 numpy ndarray 编码为字节字符串。在客户端,当您收到数据时,使用 '.fromstring()' 方法对其进行解码。我为此写了两个简单的函数。希望这会有所帮助。

  1. ndarray2str -- 将 numpy ndarray 转换为字节字符串。
  2. str2ndarray -- 将二进制 str 转换回 numpy ndarray。
    def ndarray2str(a):
        # Convert the numpy array to string 
        a = a.tostring()

        return a

在接收方,数据作为 'xmlrpc.client.Binary' 对象接收。您需要使用“.data”访问数据。

    def str2ndarray(a):
        # Specify your data type, mine is numpy float64 type, so I am specifying it as np.float64
        a = np.fromstring(a.data, dtype=np.float64)
        a = np.reshape(a, new_shape)

        return a

注意:这种方法的唯一问题是 XML-RPC 在发送大型 numpy 数组时非常慢。我花了大约 4 秒的时间为我发送和接收 (10, 500, 500, 3) 大小的 numpy 数组。

我正在使用 python 3.7.4。

【讨论】:

    【解决方案6】:

    这是对数组、数组形状和数组 dtype 进行编码的快速方法:

    def numpy_to_bytes(arr: np.array) -> str:
        arr_dtype = bytearray(str(arr.dtype), 'utf-8')
        arr_shape = bytearray(','.join([str(a) for a in arr.shape]), 'utf-8')
        sep = bytearray('|', 'utf-8')
        arr_bytes = arr.ravel().tobytes()
        to_return = arr_dtype + sep + arr_shape + sep + arr_bytes
        return to_return
    
    def bytes_to_numpy(serialized_arr: str) -> np.array:
        sep = '|'.encode('utf-8')
        i_0 = serialized_arr.find(sep)
        i_1 = serialized_arr.find(sep, i_0 + 1)
        arr_dtype = serialized_arr[:i_0].decode('utf-8')
        arr_shape = tuple([int(a) for a in serialized_arr[i_0 + 1:i_1].decode('utf-8').split(',')])
        arr_str = serialized_arr[i_1 + 1:]
        arr = np.frombuffer(arr_str, dtype = arr_dtype).reshape(arr_shape)
        return arr
    

    使用功能:

    a = np.ones((23, 23), dtype = 'int')
    a_b = numpy_to_bytes(a)
    a1 = bytes_to_numpy(a_b)
    np.array_equal(a, a1) and a.shape == a1.shape and a.dtype == a1.dtype
    

    【讨论】:

    • 感谢您的解决方案。只是一个小修复:在 numpy_to_bytes 中,输出类型应该是“bytearray”,而 bytes_to_numpy 输入类型也应该是“bytearray”。
    【解决方案7】:

    想象一下,你有一个像信使一样的 numpy 文本数组

     >>> stex[40]
     array(['Know the famous thing ...
    

    如果您想从语料库中获取统计信息(文本 col=11),您首先必须从数据帧 (df5) 中获取值,然后将所有记录连接到一个语料库中:

     >>> stex = (df5.ix[0:,[11]]).values
     >>> a_str = ','.join(str(x) for x in stex)
     >>> a_str = a_str.split()
     >>> fd2 = nltk.FreqDist(a_str)
     >>> fd2.most_common(50)
    

    【讨论】:

    • 这没有回答所提出的问题。
    • 认为不是因为 stex 是一个 numpy 数组类型(stex) 然后我将其转换为 a_str 并在 fd2 之后将 freqdist() 保存在数组中
    猜你喜欢
    • 2017-11-27
    • 2019-08-31
    • 2020-04-10
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 2017-08-14
    • 2018-11-21
    相关资源
    最近更新 更多