将numpy类型转换为python

ubh*_*ubh 35 python json numpy pandas

我有以下表格中的dicts列表,我从熊猫中生成.我想将其转换为json格式.

list_val = [{1.0: 685}, {2.0: 8}]
output = json.dumps(list_val)
Run Code Online (Sandbox Code Playgroud)

但是,json.dumps抛出一个错误:TypeError:685不是JSON可序列化的

我猜它是从numpy到python(?)的类型转换问题.

但是,当我使用np.int32(v)转换数组中每个dict的值v时,它仍会抛出错误.

编辑:这是完整的代码

            new = df[df[label] == label_new] 
            ks_dict = json.loads(content)
            ks_list = ks_dict['variables']
            freq_counts = []

            for ks_var in ks_list:

                    freq_var = dict()
                    freq_var["name"] = ks_var["name"]
                    ks_series = new[ks_var["name"]]
                    temp_df = ks_series.value_counts().to_dict()
                    freq_var["new"] = [{u: np.int32(v)} for (u, v) in temp_df.iteritems()]            
                    freq_counts.append(freq_var)

           out = json.dumps(freq_counts)
Run Code Online (Sandbox Code Playgroud)

mgi*_*son 96

看起来你是对的:

>>> import numpy
>>> import json
>>> json.dumps(numpy.int32(685))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 685 is not JSON serializable
Run Code Online (Sandbox Code Playgroud)

不幸的是,numpy数字' __repr__并没有给你任何关于它们是什么类型的暗示.int当他们不是(喘气)的时候,他们会像伪装一样跑来跑去.最终,它看起来像是json告诉你一个int不可序列化,但实际上,它告诉你这个特定的np.int32(或你实际拥有的任何类型)是不可序列化的.(没有真正的惊喜 - 没有np.int32 是可序列化的).这也是为什么传递它之前你不可避免地打印的字典json.dumps看起来它也只是整数.

这里最简单的解决方法是编写自己的序列化程序1:

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, numpy.integer):
            return int(obj)
        elif isinstance(obj, numpy.floating):
            return float(obj)
        elif isinstance(obj, numpy.ndarray):
            return obj.tolist()
        else:
            return super(MyEncoder, self).default(obj)
Run Code Online (Sandbox Code Playgroud)

你这样使用它:

json.dumps(numpy.float32(1.2), cls=MyEncoder)
json.dumps(numpy.arange(12), cls=MyEncoder)
json.dumps({'a': numpy.int32(42)}, cls=MyEncoder)
Run Code Online (Sandbox Code Playgroud)

等等

1或者您可以编写默认函数并将其作为defaut关键字参数传递给json.dumps.在这种情况下,你用最后一行替换raise TypeError,但是...... meh.该类更具可扩展性:-)

  • 为了真正的乐趣,尝试使用 `np.float64` 或 `np.bool` 一切正常,因为它们实际上是 `float` 和 `bool` 的子类。仔细想想,为什么这两种类型是子类而其他数字类型都不是,这是有道理的,但是直到你这样做,它才能让调试变得有趣…… (3认同)