4

我有一个numpy数组,我想用 Json 转储。数组如下所示:

array([['foo', 'bar', 'something', ...
        'more'],
        ['0.4', '0.7', '0.83', ...
        '0.3', '0.62', '0.51']]

我想用 Json将它转储到一个字符串上,如下所示:

foo: 0.4
bar: 0.7
something: 0.51
...

我尝试过:

import jason
my_string = json.dumps(my_array)

但它抱怨:

"not JSON serializable"

关于如何使用 Json将其转储到字符串上的任何想法?

更新:

请不要说我关心订购,应按以下顺序打印行:

array[0,0] : array[0,1]
array[1,0] : array[1,1]
array[2,0] : array[2,1]
# etc ...
4

5 回答 5

7

对我有用的东西——因为有更大的 1024x1002 的 float64 数组——是转换为 base64。

def Base64Encode(ndarray):
    return json.dumps([str(ndarray.dtype),base64.b64encode(ndarray),ndarray.shape])
def Base64Decode(jsonDump):
    loaded = json.loads(jsonDump)
    dtype = np.dtype(loaded[0])
    arr = np.frombuffer(base64.decodestring(loaded[1]),dtype)
    if len(loaded) > 2:
        return arr.reshape(loaded[2])
    return arr

''' just to compare '''
def SimpleEncode(ndarray):
    return json.dumps(ndarray.tolist())
def SimpleDecode(jsonDump):
    return np.array(json.loads(jsonDump))

ipython %timeit 结果非常清楚地指向base64:

arr = np.random.random_sample((1000, 1000))

print 'Simple Convert'
%timeit SimpleDecode(SimpleEncode(arr))
print 'Base64 Encoding'
%timeit Base64Decode(Base64Encode(arr))

结果:

Simple Convert
1 loops, best of 3: 1.42 s per loop
Base64 Encoding
10 loops, best of 3: 171 ms per loop
于 2013-10-09T11:54:30.363 回答
1

不确定 JSON 可序列化部分,但您可以先将其转换为 dict 吗?这似乎是一种更自然的 JSON 输出格式,并且可以处理数据类型的任何问题。

my_dict = dict(zip(my_array[1], my_array[0]))

于 2012-11-19T21:04:48.347 回答
0

如果所有值都是数字,如果其他一切都失败了,您总是可以手动执行:

my_array = [['0.4', '0.7', '0.83', '0.3', '0.62', '0.51'],
            ['foo', 'bar', 'something', 'more']]

pairs = zip(my_array[1], my_array[0])
json_values = ('"{}": {}'.format(label, value) for label, value in pairs)
my_string = '{' + ', '.join(json_values) + '}'

print my_string # '{"foo": 0.4, "bar": 0.7, "something": 0.83, "more": 0.3}'
于 2012-11-19T21:05:31.763 回答
0

如果您只是想获得数组的漂亮字符串表示,并且使用字符串数组类型并不能提供您想要的表示,那么消息序列化格式不是要使用的东西。序列化格式用于保存/传输数据。Json 很好,因为它通常也是人类可读的,但这不是目的,强制将其转换为不同的格式会使其不再是 json 序列化。即使 savetxt 和 loadtxt numpy 选项也不适用于您想要的格式(重复每一列的第一行)。如果必须采用该格式,您可以使用以下代码进行自己的序列化:

def prettySerialize(inArray):
    ids = inArray[0]
    strRep = ''

    for row in inArray[1:]:
        for i,item in enumerate(row):
            rowStr = id[i] + ':' + item + '\n'
            strRep += rowStr

    return strRep

这样做的问题是它会慢得多,并且数组的表示形式要大得多(一遍又一遍地重复“id”行)。我强烈建议您使用纯 json(或 msgpack)解决方案,除非您专门将其格式化以供人类阅读......

这是我用于使用 msgpack 进行序列化的解决方案(也适用于 json)... 转换为包含 dtype 和数组形状的元组:

def arrayToTuple(arr):
    if arr is None:
        return None

    return (arr.dtype.str, arr.shape, arr.tostring())

def arrayFromTuple(tupl):
    if tupl is None:
        return None

    typeStr, shape, dataStr = tupl

    resultArray = numpy.fromstring(dataStr, dtype=typeStr).reshape(shape)

    return resultArray

所以转储和加载命令将是:

strRep = json.dumps(arrayToTuple(arr))
arrayFromTuple(json.loads(strRep))

这也适用于 msgpack.dumps 和 msgpack.loads(一种更快更紧凑的二进制表示)。

可能适用于您的数组的警告:如果您的 numpy 数组是对象 dtype,则它不会通过标准方法序列化为完整数组。您必须单独序列化每个对象,因为它是存储在数组中的对象 ID,而不是数据。使用 dtype 作为 dtype='|S' 其中是最大字符串长度将使数组可序列化。

于 2012-11-19T22:37:56.897 回答
-1

我只使用过一点 numpy,但我认为它在内部以特殊格式保存数据,所以 json 模块不知道如何处理它是有道理的。

将其转换回数组是否有效?

json.dumps(numpy.asarray(my_array))

http://docs.scipy.org/doc/numpy/reference/generated/numpy.asarray.html

于 2012-11-19T21:03:14.880 回答