Массив NumPy не является сериализуемым JSON


после создания массива NumPy и сохранения его в качестве переменной контекста Django, я получаю следующую ошибку при загрузке веб-страницы:

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

что это значит?

11 91

11 ответов:

Я регулярно "jsonify" np.матрицы. Попробуйте использовать ".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)
class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

a = np.массив([1, 2, 3])

print(json.свалки ({'aa': [2, (2, 3, 4), a], 'bb': [2]}, cls=NumpyEncoder))

{"aa": [2, [2, 3, 4], [1, 2, 3]], "bb": [2]}

можно использовать панды:

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

Я нашел лучшее решение, если у вас есть вложенные массивы numpy в словарь:

import json
import numpy as np

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy types """
    def default(self, obj):
        if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
            np.int16, np.int32, np.int64, np.uint8,
            np.uint16, np.uint32, np.uint64)):
            return int(obj)
        elif isinstance(obj, (np.float_, np.float16, np.float32, 
            np.float64)):
            return float(obj)
        elif isinstance(obj,(np.ndarray,)): #### This is the fix
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

dumped = json.dumps(data, cls=NumpyEncoder)

with open(path, 'w') as f:
    json.dump(dumped, f)

спасибо этот парень.

Это не поддерживается по умолчанию, но вы можете сделать это довольно легко работать! Есть несколько вещей, которые вы хотите кодировать, если вы хотите точно такие же данные:

  • сами данные, которые вы можете сделать с obj.tolist() Как упоминалось в @travelingbones. Иногда это может быть достаточно хорошим.
  • тип данных. Я чувствую, что это важно в некоторых случаях.
  • размер (не обязательно 2D), который может быть получен из вышеизложенного, если вы предполагаете ввод это действительно всегда "прямоугольная" сетка.
  • порядок памяти (строк или столбцов). Это не часто имеет значение, но иногда это так (например, производительность), так почему бы не сохранить все?

кроме того, Ваш массив numpy может быть частью вашей структуры данных, например, у вас есть список с некоторыми матрицами внутри. Для этого вы можете использовать пользовательский кодер, который в основном делает выше.

этого должно быть достаточно для реализации решения. Или вы могли бы использовать в JSON-приколы который делает именно это (и поддерживает различные другие типы) (отказ от ответственности: я сделал это).

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

У меня была аналогичная проблема с вложенным словарем с некоторым 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

кроме того, некоторые очень интересные сведения о списках и массивах в Python ~> список Python против массива-когда использовать?

можно отметить, что после того, как я преобразовать массивы в список, прежде чем сохранить его в формате JSON файл, в моем развертывание прямо сейчас, в любом случае, когда-то я читал, что JSON-файла для дальнейшего использования, я могу продолжать использовать его в виде списка (а не преобразовать его обратно в массив).

и на самом деле выглядит лучше (на мой взгляд) на экране в качестве список (запятая разделена) против массива (не-запятая разделена) таким образом.

С помощью @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')

надеюсь, что это помогает!

вот реализация, которая работает для меня и удалила все nans (предполагая, что это простой объект (list или dict)):

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

это другой ответ, но это может помочь помочь людям, которые пытаются сохранить данные, а затем прочитать его снова.
Есть хикл, который быстрее, чем рассол и проще.
Я попытался сохранить и прочитать его в pickle dump, но во время чтения было много проблем и потратил впустую час и до сих пор не нашел решения, хотя я работал над своими собственными данными, чтобы создать чат-бота.

vec_x и vec_y массивы numpy:

data=[vec_x,vec_y]
hkl.dump( data, 'new_data_file.hkl' )

тогда вы просто читать это и выполняют операции:

data2 = hkl.load( 'new_data_file.hkl' )

вы также можете использовать например:

def myconverter(o):
    if isinstance(o, np.float32):
        return float(o)

json.dump(data, default=myconverter)

все остальные кодеры numpy кажутся немного слишком сложными. проверьте, если объект, если из модуля numpy, если так использовать numpy.item, он работает для любого конкретного типа numpy.

import numpy as np
import json

class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if type(obj).__module__ == np.__name__:
            return obj.item()
        return json.JSONEncoder.default(self, obj)

dumped = json.dumps(data, cls=NumpyEncoder)