Matriz NumPy no es serializable JSON


Después de crear una matriz NumPy, y guardarla como una variable de contexto Django, recibo el siguiente error al cargar la página web:

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

¿Qué significa esto?

Author: Rodrigo de Azevedo, 2014-10-30

11 answers

Regularmente "jsonify" np.matriz. Trate de usar el".tolist () " método en los arrays primero, así:

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

Para" unjsonify " el uso de la matriz:

obj_text = codecs.open(file_path, 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
a_new = np.array(b_new)
 135
Author: travelingbones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-29 17:44:51
class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

A = np.matriz([1, 2, 3])

Print (json.vertederos({'aa': [2, (2, 3, 4), a], 'bb': [2]}, cls=NumpyEncoder))

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

 63
Author: karlB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-04 04:58:51

Puedes usar Pandas :

import pandas as pd
pd.Series(your_array).to_json(orient='values')
 22
Author: John Zwinck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-26 01:52:40

He encontrado la mejor solución si ha anidado matrices numpy en un diccionario:

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)

Gracias a este tipo.

 8
Author: tsveti_iko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-05 16:33:16

Esto no es soportado por defecto, pero puedes hacer que funcione muy fácilmente! Hay varias cosas que usted querrá codificar si desea exactamente los mismos datos de vuelta:

  • Los datos en sí, que puede obtener con obj.tolist() como @travelingbones mencionado. A veces esto puede ser suficiente.
  • El tipo de datos. Creo que esto es importante en algunos casos.
  • La dimensión (no necesariamente 2D), que podría derivarse de lo anterior si asume que la entrada es siempre una cuadrícula rectangular.
  • El orden de la memoria (fila - o columna-mayor). Esto a menudo no importa, pero a veces sí (por ejemplo, rendimiento), así que ¿por qué no guardar todo?

Además, su matriz numpy podría formar parte de su estructura de datos, por ejemplo, tiene una lista con algunas matrices dentro. Para eso se puede utilizar un codificador personalizado que básicamente hace lo anterior.

Esto debería ser suficiente para implementar una solución. O podrías usar json-tricks que hace justo esto (y soporta varios otros tipos) (descargo de responsabilidad: Lo hice).

pip install json-tricks

Entonces

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))
 2
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-19 17:56:12

Tuve un problema similar con un diccionario anidado con algunos numpy.ndarrays en él.

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
 1
Author: JLT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-12 19:03:08

También hay información muy interesante sobre listas vs. arrays en Python ~> Lista de Python vs. Array - ¿cuándo usar?

Se podría notar que una vez que convierta mis matrices en una lista antes de guardarlas en un archivo JSON, en mi implementación ahora mismo de todos modos, una vez que lea ese archivo JSON para usarlo más tarde, puedo continuar usándolo en forma de lista (en lugar de convertirlo de nuevo a una matriz).

Y en realidad se ve mejor (en mi opinión) en la pantalla como una lista (coma separados) vs una matriz (no-separados por comas) de esta manera.

Usando @travelingbones.el método tolist () anterior, he estado usando como tal (capturando algunos errores que también he encontrado):

GUARDAR DICCIONARIO

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

LEA EL DICCIONARIO

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

Espero que esto ayude!

 0
Author: ntk4,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:50

Aquí hay una implementación que funciona para mí y eliminó todas las nan (asumiendo que son objetos simples (lista o 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
 0
Author: Roei Bahumi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-09 12:08:19

Esta es una respuesta diferente, pero esto podría ayudar a ayudar a las personas que están tratando de guardar datos y luego leerlos de nuevo.
Hay hickle que es más rápido que encurtido y más fácil.
Intenté guardarlo y leerlo en pickle dump, pero mientras leía hubo muchos problemas y desperdicié una hora y aún no encontré la solución, aunque estaba trabajando en mis propios datos para crear un chat bot.

vec_x y vec_y son matrices numpy:

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

Entonces usted acaba de leerlo y realizar el operaciones:

data2 = hkl.load( 'new_data_file.hkl' )
 0
Author: KS HARSHA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-13 21:57:29

También puedes usar el argumento default por ejemplo:

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

json.dump(data, default=myconverter)
 0
Author: steco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-21 13:01:31

Todos los otros codificadores numpy parecen un poco demasiado complicados. comprobar si el objeto si desde el módulo numpy si es así utilizar numpy.item, funciona para cualquier tipo específico 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)
 0
Author: moshevi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-02 08:32:41