Mpld3: "TypeError: *** no es JSON serializable" al usar xticks

Creado en 11 may. 2014  ·  29Comentarios  ·  Fuente: mpld3/mpld3

Encontré este error cuando estaba jugando con la trama de pandas, cuando uso el argumento xticks .

La prueba de concepto está aquí:
http://nbviewer.ipython.org/gist/edvakf/a47a41ace10afbd891ff
(modificación de http://pandas.pydata.org/pandas-docs/stable/visualization.html )

Comentario más útil

Lo arreglé agregando la línea

elif isinstance(obj, (numpy.ndarray,)):
        return obj.tolist()

a /mpld3/_display.py: NumpyEncoder

Todos 29 comentarios

Ah, parece que mplexporter asume incorrectamente que los xticks son una lista. Eso es un error.

Mientras tanto, si convierte manualmente sus xticks en una lista, debería funcionar.

En realidad, ese no es el caso. Es decir, lo siguiente funciona bien:

fig = plt.figure()
ax = fig.add_subplot(111, xticks=np.arange(11))
ax.plot([0, 10], [0, 10], '-k')
mpld3.show()

Pandas está haciendo algo extraño aquí con sus ticks: el error dice que 2000 no es serializable, lo cual es una locura. ¿Pandas tiene algún tipo de tipo de punto flotante no serializable incorporado?

No es el número 2000, es el año. Bienvenido al infierno datetime .
(editar 19/6/2014: parece que me equivoqué acerca de que datetime era el problema...)

Uf... No estoy seguro de cuál es la mejor manera de manejar eso. ¿Alguna idea?

¿Ayuda usar to_json en pandas ?

http://pandas.pydata.org/pandas-docs/dev/io.html#date -manejo

¿Ayuda usar to_json en pandas?

Tal vez, pero luego tendremos que hacer una declaración try ... except para muchas cosas dentro del código (es decir, hacerlo de una manera si el valor es una variable de Pandas, hacer de otra manera) y luego asegúrese de que las etiquetas de eje en el lado de javascript puedan manejar cualquier estructura JSON que Pandas decida generar. Preferiría no agregar ese nivel de complejidad, porque suena como una solución muy frágil y una pesadilla de mantenimiento.

Veo. Esto se reduce a la incapacidad de Python para exponer el método de serialización json para la clase definida por el usuario. Puede cerrar este problema.

Deberíamos dejarlo abierto... puede haber una mejor manera de manejar esto. Lo pensare.

Espera un segundo, esto parece funcionar bien para mí en Python 2.7. ¿Podría ser solo un problema de Python3?

In [56]: matplotlib.__version__
Out[56]: '1.3.1'

In [57]: pandas.__version__
Out[57]: '0.13.1'

Hola a todos,
No estoy seguro si está relacionado, pero tengo un problema similar al intentar trazar este gráfico marino: http://www.stanford.edu/~mwaskom/software/seaborn/examples/many_facets.html

mpld3.fig_to_html(grid.fig, 'test.html')
/home/vagrant/graph/local/lib/python2.7/site-packages/mpld3/mplexporter/exporter.py:82: UserWarni ng: Blended transforms not yet supported. Zoom behavior may not work as expected.
  warnings.warn("Blended transforms not yet supported. "
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/vagrant/graph/local/lib/python2.7/site-packages/mpld3/_display.py", line 236, in fig_to_html
    figure_json=json.dumps(figure_json),
  File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 0 is not JSON serializable

El problema es que los números numpy.int64 se usan internamente y no son json serializables de forma predeterminada.
Debería haber un enlace en la biblioteca para proporcionar un json.JSONEncoder para manejar esto.

Solo para dar espacio a las ideas:

Tengo el mismo problema, pero conectado a Django, que es lo que uso como backend para el proyecto que estoy usando en el proyecto donde uso mpld3.

Intenté serializar una matriz numpy y obtuve este error al usar django 1.6. Bajé a 1.5 y funciona. Encontré que la razón es que a partir de la 1.6 en adelante, la serialización se realiza con json, mientras que a partir de la 1.5 y posteriores, a través de Pickle.

Espero que esto pueda ayudarlos a encontrar el problema.

med vennlig hilsen,
Gerardo de la Riva Espinosa
Høgskolelektor
Høgskolen y Gjøvik
e-post: gerardo. [email protected]
Móvil: +47 950 13 322

El 19 de junio de 2014, a las 16:56, lvasseur [email protected] escribió:

Hola a todos,
No estoy seguro si está relacionado, pero tengo un problema similar al intentar trazar este gráfico marino: http://www.stanford.edu/~mwaskom/software/seaborn/examples/many_facets.html

mpld3.fig_to_html(grid.fig, 'prueba.html')
/home/vagrant/graph/local/lib/python2.7/site-packages/mpld3/mplexporter/exporter.py:82: UserWarni ng: Las transformaciones combinadas aún no son compatibles. Es posible que el comportamiento del zoom no funcione como se esperaba.
advertencias.warn("Las transformaciones combinadas aún no son compatibles. "
Rastreo (llamadas recientes más última):
Archivo "", línea 1, en
Archivo "/home/vagrant/graph/local/lib/python2.7/site-packages/mpld3/_display.py", línea 236, en fig_to_html
figura_json=json.dumps(figura_json),
Archivo "/usr/lib/python2.7/json/__init__.py", línea 231, en vertederos
devolver _default_encoder.encode(obj)
Archivo "/usr/lib/python2.7/json/encoder.py", línea 201, en codificar
fragmentos = self.iterencode(o, _one_shot=True)
Archivo "/usr/lib/python2.7/json/encoder.py", línea 264, en iterencode
devuelve _iterencode(o, 0)
Archivo "/usr/lib/python2.7/json/encoder.py", línea 178, por defecto
aumentar TypeError (repr (o) + "no es JSON serializable")
TypeError: 0 no es JSON serializable
El problema es que los números numpy.int64 se usan internamente y no son json serializables de forma predeterminada.
Debería haber un enlace en la biblioteca para proporcionar un json.JSONEncoder para manejar esto.


Responda a este correo electrónico directamente o véalo en GitHub.

para tu información,

    from json import JSONEncoder
    class MyEncoder(JSONEncoder):
        def default(self, obj):
            if isinstance(obj, numpy.int64):
                return int(obj)
            return JSONEncoder.default(self, obj)

    return template.render(figid=json.dumps(figid),
                           d3_url=d3_url,
                           mpld3_url=mpld3_url,
                           figure_json=json.dumps(figure_json, cls=MyEncoder),
                           extra_css=extra_css,
                           extra_js=extra_js)

resuelve el problema en /mpld3/_display.py: fig_to_html

No tengo tiempo para intentarlo ahora, pero parece que este es un problema y la dirección correcta para una solución. Los documentos json.dump me hacen pensar que existe una solución un poco más liviana con la opción default , aunque al final podría ser solo una línea más corta. ¿Estás listo para hacer una solicitud de extracción?

Esperaba que esto se arreglara con PR #213, pero el cuaderno de ipython de la publicación original todavía no funciona para mí. ¿Alguien más puede intentarlo?

Voy a darle una oportunidad a esto en algún momento

Todavía confundido por esto... No estoy seguro de si #213 realmente arregló algo aquí. Puedo serializar objetos int64 sin él...

se soluciono esto?
Parece que no puedo fig_to_html una figura generada por pandas (obtengo TypeError: 0 is not JSON serializable ). La figura se genera bien.
Cuando volví a intentarlo usando plt.bar, también aparece el error si uso yticks con cadenas personalizadas.

¿Cómo resolver?

No estoy seguro. Parece haber algún problema con las etiquetas de eje que son versiones no serializables de enteros. Si descubres algo, háznoslo saber.

Solo quería señalar que recibo este error cuando uso

dates = df.Date.apply(lambda dt: dt.strftime('%B')[:3] + dt.strftime(' %d')).values
plt.xticks(x, dates, rotation='vertical')

pero no con

ax.set_xticklabels(dates, rotation='vertical')

Espero que esto ayude.

Editar: en una inspección más detallada, aunque la última versión no produce un error, los xticks de la figura resultante en realidad no se configuran.

Edición 2: Mi error, acabo de descubrir que los ticks no son compatibles (n. ° 22).

FWIW, usar diagramas de caja puede reproducir el problema:

import numpy as np, mpld3
np.random.seed(937)
data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
labels = list('ABCD')
fs = 10  # fontsize

fig, axes = plt.subplots(1, 1, figsize=(6, 6)) 
axes.boxplot(data, labels=labels)
axes.set_title('Default', fontsize=fs)

html_fig = mppld3.fig_to_html(fig)

Específicamente, aquí están las versiones de pip freeze.

cycler==0.10.0
Jinja2==2.8
MarkupSafe==0.23
matplotlib==1.5.1
mpld3==0.2
numpy==1.10.4
pandas==0.17.1
ptyprocess==0.5.1
pyparsing==2.1.0
python-dateutil==2.5.0
pytz==2015.7
six==1.10.0
wheel==0.29.0

para Python 3.4.3.

El parche sugerido por @lvasseur parece solucionar el problema, aunque no sé si es _la_ solución.

Para que el ejemplo original funcione, use [float(x) for x in range(2000,2002)] en lugar de np.arange(2000,2002,1).

No estoy seguro si está relacionado, pero tengo un problema similar al intentar trazar este gráfico marino: http://www.stanford.edu/~mwaskom/software/seaborn/examples/many_facets.html

Obtengo el mismo error al probar mtld3.display(fig) para la figura de gráfico de barras seaborn:

TypeError: 0 no es JSON serializable

¿Alguien puede renderizar tramas marinas con mpld3?

Esto parece suceder porque hay nan en valores de datos. Si rompo en _display.py:243nan con None en figure_json dict, obtengo el resultado esperado.

Editar: lo anterior no parece resolver el problema (estaba probando en el intérprete de depuración, donde funcionó pero no cuando usaba mpld3).
Entonces, renderizar sns.barplot() no funciona, mientras que renderizar plt.bar() funciona bien. No pude ver una diferencia obvia en las cifras de ambos gráficos, pero el parche provisto (https://github.com/mpld3/mpld3/pull/213) resolvió el problema.

Lo arreglé agregando la línea

elif isinstance(obj, (numpy.ndarray,)):
        return obj.tolist()

a /mpld3/_display.py: NumpyEncoder

Gracias @jaklinger esto funcionó!!!

@jaklinger , Hola, gracias por tu sugerencia, ¡funciona perfectamente! Solo quería aclarar una cosa: convertí la matriz numpy en un diccionario e intenté devolverlo, pero arrojaba el error "float 32 is not json serializable", aunque no hubo ningún problema con el diccionario, lo imprimí y lo verifiqué. Simplemente usando su método tolist(), convirtió la matriz en una lista de python.
anterior :[100. 0. 0. 0. 0.]
con tolist: [100.0, 0.0, 0.0, 0.0, 0.0] y volvió perfectamente.
Entonces, ¿cuál era exactamente el problema? Muchas gracias de antemano.

@ padmaksha18 No estoy 100% seguro de lo que quieres decir con

convirtió la matriz numpy en un diccionario

pero (resumiendo) los tipos numpy y python no son lo mismo ( float32 no es lo mismo que un float ; un array no es lo mismo que list , etc.) y la clase JSONEncoder solo 'permite' tipos nativos de python . Entonces... el objetivo de esta función (que contiene la nueva solución) es convertir la entrada obj en python nativos de

@jaklinger : Hola Joel, muchas gracias de nuevo. Al convertir a un diccionario, solo quise decir que tomé dos de esas matrices y formé un par de valores clave, lo siento por no explicarlo claramente. Muchas gracias por aclararme esto, primero debo convertirlo al tipo nativo de python y ese fue el problema. Solo quería aclarar una cosa más, como si no jsonifica un diccionario y trata de devolverlo tal como está, ¿aparecerá la clase jsonencoder en la imagen entonces? ¡Muchas gracias!

instalación de pip "git+ https://github.com/javadba/mpld3@display_fix "

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

arnaudrenaud picture arnaudrenaud  ·  4Comentarios

omn14 picture omn14  ·  17Comentarios

pranet picture pranet  ·  6Comentarios

jakevdp picture jakevdp  ·  4Comentarios

dmiller7115 picture dmiller7115  ·  5Comentarios