Подтвердить что ты не робот

Преобразование типа numpy в python

У меня есть список dicts в следующем виде, который я генерирую из pandas. Я хочу преобразовать его в формат json.

list_val = [{1.0: 685}, {2.0: 8}]
output = json.dumps(list_val)

Однако json.dumps выдает ошибку: TypeError: 685 не является сериализуемым JSON

Я предполагаю, что это проблема преобразования типов из numpy в python (?).

Однако, когда я конвертирую значения v каждого dict в массив с помощью np.int32 (v), он все равно выдает ошибку.

EDIT: здесь полный код

            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)
4b9b3361

Ответ 1

Похоже, ты прав:

>>> 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

К сожалению, здесь то, что числовые числа __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)

Вы используете это так:

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

и т.п.

1 Или вы можете просто написать функцию по умолчанию и передать ее в качестве defaut ключевого слова json.dumps в json.dumps.В этом случае вы бы заменили последнюю строку на raise TypeError, но... ме.Класс более расширяемый :-)

Ответ 2

Вы также можете преобразовать массив в список python (используйте метод tolist), а затем преобразовать список в json.

Ответ 3

Если вы оставите данные в любом из объектов pandas, библиотека поставляет функцию to_json для Series, DataFrame и всех других кузенов большего размера.

Смотрите Series.to_json()

Ответ 4

Вы можете использовать наш форк ujson для работы с NumPy int64. caiyunapp/ultrajson: сверхбыстрый JSON-декодер и кодер, написанный на C с привязками Python и NumPy

pip install nujson

затем

>>> import numpy as np
>>> import nujson as ujson
>>> a = {"a": np.int64(100)}
>>> ujson.dumps(a)
'{"a":100}'
>>> a["b"] = np.float64(10.9)
>>> ujson.dumps(a)
'{"a":100,"b":10.9}'
>>> a["c"] = np.str_("12")
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12"}'
>>> a["d"] = np.array(list(range(10)))
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12","d":[0,1,2,3,4,5,6,7,8,9]}'
>>> a["e"] = np.repeat(3.9, 4)
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12","d":[0,1,2,3,4,5,6,7,8,9],"e":[3.9,3.9,3.9,3.9]}'