2014-10-30 102 views
45

创建与NumPy阵列,并将其保存为一个Django上下文变量后,加载网页时,我收到以下错误:NumPy的阵列是不是JSON序列化

array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable 

这是什么意思?

+13

这意味着某个地方,一些试图转储numpy的阵列使用'json'模块。但'numpy.ndarray'不是'json'知道如何处理的类型。你可能需要编写自己的序列化程序,或者(更简单地说)只要将'list(your_array)'传递给正在写入json的任何东西。 – mgilson 2014-10-30 06:26:57

+6

注意'名单(your_array)'并不总是可行的,因为它返回numpy的整数,而不是原生整数。改用'your_array.to_list()'。 – ashishsingal 2017-01-04 21:16:42

+7

关于@ ashishsingal的评论注意到,它应该是your_array.tolist(),而不是to_list()。 – vega 2017-03-17 16:52:59

回答

92

我经常“jsonify”np.arrays。尝试首先使用在阵列上的“.tolist()”的方法,是这样的:

import numpy as np 
import codecs, json 

a = np.arange(10).reshape(2,5) # a 2 by 5 array 
b = a.tolist() # nested lists with same data, indices 
file_path = "/path.json" ## your path variable 
json.dump(b, codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4) ### this saves the array in .json format 

为了‘unjsonify’阵列使用:

obj_text = codecs.open(file_path, 'r', encoding='utf-8').read() 
b_new = json.loads(obj_text) 
a_new = np.array(b_new) 
+1

为什么只能将它作为列表列表存储? – 2017-11-07 15:12:35

+0

我不知道,但我期望np.array类型具有不适合json的元数据(例如,他们指定每个条目的数据类型,如float) – travelingbones 2017-11-07 18:25:56

+0

我试过你的方法,但似乎程序在' tolist()'。 – 2018-01-31 12:38:22

0

此外,一些很有趣的信息上进一步列表与数组在Python〜>Python List vs. Array - when to use?

可以注意到,一旦我将我的数组转换成列表之前,将其保存在JSON文件中,在我的部署中,无论如何,一旦我读取JSON文件供以后使用,我可以继续以列表形式使用它(而不是转换回到数组)。

AND在屏幕上看起来更好(在我看来)列表(逗号分隔)与数组(不逗号分隔)这种方式。

使用@ travelingbones的.tolist()方法上面,我一直在利用这样(捕了一些错误,我发现太):

储存字典

def writeDict(values, name): 
    writeName = DIR+name+'.json' 
    with open(writeName, "w") as outfile: 
     json.dump(values, outfile) 

读字典

def readDict(name): 
    readName = DIR+name+'.json' 
    try: 
     with open(readName, "r") as infile: 
      dictValues = json.load(infile) 
      return(dictValues) 
    except IOError as e: 
     print(e) 
     return('None') 
    except ValueError as e: 
     print(e) 
     return('None') 

希望这会有所帮助!

0

这里是为我工作,并删除了所有的NaN(假设这些都是简单的对象(列表或字典))的实现:

from numpy import isnan 

def remove_nans(my_obj, val=None): 
    if isinstance(my_obj, list): 
     for i, item in enumerate(my_obj): 
      if isinstance(item, list) or isinstance(item, dict): 
       my_obj[i] = remove_nans(my_obj[i], val=val) 

      else: 
       try: 
        if isnan(item): 
         my_obj[i] = val 
       except Exception: 
        pass 

    elif isinstance(my_obj, dict): 
     for key, item in my_obj.iteritems(): 
      if isinstance(item, list) or isinstance(item, dict): 
       my_obj[key] = remove_nans(my_obj[key], val=val) 

      else: 
       try: 
        if isnan(item): 
         my_obj[key] = val 
       except Exception: 
        pass 

    return my_obj 
1

我有一个嵌套的字典,一些numpy.ndarrays类似的问题在里面。

def jsonify(data): 
    json_data = dict() 
    for key, value in data.iteritems(): 
     if isinstance(value, list): # for lists 
      value = [ jsonify(item) if isinstance(item, dict) else item for item in value ] 
     if isinstance(value, dict): # for nested lists 
      value = jsonify(value) 
     if isinstance(key, int): # if key is integer: > to string 
      key = str(key) 
     if type(value).__module__=='numpy': # if value is numpy.*: > to python list 
      value = value.tolist() 
     json_data[key] = value 
    return json_data 
12

您可以使用Pandas

import pandas as pd 
pd.Series(your_array).to_json(orient='values') 
+2

太棒了!我认为对于2D np.array,它会像'pd.DataFrame(your_array).to_json('data.json',orient ='split')'。 – nix 2017-08-19 21:38:07

+0

如何将数据转化为数组? – 2018-01-31 14:39:06

+0

@yurenzhong:什么数据?也许你应该发表一个你自己的问题? – 2018-02-01 00:56:13

1

这是默认不支持,但你可以把它很容易地工作!还有,如果你想完全一样的数据回你要编码几件事情:

  • 数据本身,您可以与obj.tolist()得到尽可能@travelingbones提及。有时候这可能会很好。
  • 数据类型。我觉得在某些情况下这很重要。
  • 尺寸(不一定是2D),如果您假设输入确实总是一个“矩形”网格,则可以从上面得出这个尺寸。
  • 内存顺序(行或列主要)。这通常不重要,但有时它确实(例如表演),那么为什么不保存所有东西呢?

此外,您的numpy的阵列可以你的数据结构的一部分,例如你有一个列表,里面有一些矩阵。为此,你可以使用一个自定义的编码器,基本上是这样做的。

这应该足以实现解决方案。或者你可以使用json-tricks这不只是这一点(和支持各种其他类型)(声明:我做到了)。

pip install json-tricks 

然后

data = [ 
    arange(0, 10, 1, dtype=int).reshape((2, 5)), 
    datetime(year=2017, month=1, day=19, hour=23, minute=00, second=00), 
    1 + 2j, 
    Decimal(42), 
    Fraction(1, 3), 
    MyTestCls(s='ub', dct={'7': 7}), # see later 
    set(range(7)), 
] 
# Encode with metadata to preserve types when decoding 
print(dumps(data)) 
16
class NumpyEncoder(json.JSONEncoder): 
    def default(self, obj): 
     if isinstance(obj, np.ndarray): 
      return obj.tolist() 
     return json.JSONEncoder.default(self, obj) 

一个= np.array([1,2,3])

打印(json.dumps({ 'AA':[ 2,(2,3,4),a],'bb':[2]}, cls = NumpyEncoder))

{ “AA”:[2,[2,3,4],[1,2,3]], “BB”:[2]}

+3

这应该比董事会更高,这是这样做的一般化和适当抽象的方式。谢谢! – thclark 2018-01-18 15:12:25

+0

是否有一种简单的方法从列表中获取ndarray? – DarksteelPenguin 2018-02-23 16:47:34