Mpld3: «TypeError: *** не сериализуем JSON» при использовании xticks

Созданный на 11 мая 2014  ·  29Комментарии  ·  Источник: mpld3/mpld3

Я столкнулся с этой ошибкой, когда возился с сюжетом панд, когда использовал аргумент xticks .

Доказательство концепции здесь:
http://nbviewer.ipython.org/gist/edvakf/a47a41ace10afbd891ff
(модификация http://pandas.pydata.org/pandas-docs/stable/visualization.html)

Самый полезный комментарий

Я исправил это, добавив строку

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

в /mpld3/_display.py: NumpyEncoder

Все 29 Комментарий

Ах, похоже, mplexporter неправильно предполагает, что xticks — это список. Это ошибка.

Тем временем, если вы вручную преобразуете свои xticks в список, это должно сработать.

На самом деле это не так. То есть следующее работает нормально:

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

Pandas делает здесь что-то странное со своими тиками: ошибка говорит, что 2000 не сериализуема, что безумие. Есть ли в Pandas какой-то встроенный несериализуемый тип с плавающей запятой?

Это не число 2000, это год. Добро пожаловать в ад datetime .
(редактировать 19.06.2014: кажется, я ошибался в том, что datetime является проблемой...)

Тьфу... Я не знаю, как лучше с этим справиться. Есть предположения?

Помогает ли использование to_json в pandas ?

http://pandas.pydata.org/pandas-docs/dev/io.html#date-обработка

Помогает ли использование to_json в пандах?

Возможно, но тогда нам придется сделать оператор try ... except для многих вещей в коде (т.е. сделать это одним способом, если значение является переменной Pandas, сделать иначе), а затем убедитесь, что метки осей на стороне javascript могут обрабатывать любую структуру JSON, которую Pandas решает вывести. Я бы предпочел не добавлять этот уровень сложности, потому что это звучит как очень хрупкое решение и кошмар обслуживания.

Я понимаю. Это сводится к неспособности Python предоставить метод сериализации json для определяемого пользователем класса. Вы можете закрыть этот вопрос.

Мы должны оставить его открытым... может быть, есть лучший способ справиться с этим. Я подумаю об этом.

Подождите секунду, у меня это отлично работает в Python 2.7. Может ли это быть проблемой только Python3?

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

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

Привет всем,
Не уверен, что это связано, но у меня возникает аналогичная проблема при попытке построить этот морской график: 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

Проблема в том, что числа numpy.int64 используются внутри, и что по умолчанию они не сериализуются json.
В библиотеке должен быть хук, чтобы предоставить json.JSONEncoder для обработки этого.

Просто чтобы дать место для идей:

У меня та же проблема, но я подключен к Django, который я использую в качестве бэкэнда для проекта, который я использую в проекте, где я использую mpld3.

Я попытался сериализовать массив numpy и получил эту ошибку при использовании django 1.6. Понизил до 1.5 и все работает. Я обнаружил, что причина в том, что с версии 1.6 и выше сериализация выполняется с помощью json, а с версии 1.5 и ниже — с помощью Pickle.

Я надеюсь, что это может помочь вам, ребята, найти проблему.

Med vennlig hilsen,
Херардо де ла Рива Эспиноса
Høgkolelektor
Høgskolen i Gjøvik
электронная почта: gerardo. [email protected]
Мобильный: +47 950 13 322

С 19 июня 2014 г., 16:56, lvasseur [email protected] писал:

Привет всем,
Не уверен, что это связано, но у меня возникает аналогичная проблема при попытке построить этот морской график: 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: Предупреждение пользователя: смешанные преобразования еще не поддерживаются. Масштабирование может работать не так, как ожидалось.
warnings.warn("Смешанные преобразования еще не поддерживаются."
Traceback (последний последний вызов):
Файл "", строка 1, в
Файл "/home/vagrant/graph/local/lib/python2.7/site-packages/mpld3/_display.py", строка 236, в fig_to_html
Figure_json=json.dumps(figure_json),
Файл "/usr/lib/python2.7/json/__init__.py", строка 231, в дампах
вернуть _default_encoder.encode (объект)
Файл "/usr/lib/python2.7/json/encoder.py", строка 201, в кодировке
куски = self.iterencode(o, _one_shot=True)
Файл "/usr/lib/python2.7/json/encoder.py", строка 264, в iterencode
вернуть _iterencode (о, 0)
Файл "/usr/lib/python2.7/json/encoder.py", строка 178, по умолчанию
поднять TypeError (repr (o) + "не сериализуем JSON")
TypeError: 0 не сериализуем JSON
Проблема в том, что числа numpy.int64 используются внутри, и что по умолчанию они не сериализуются json.
В библиотеке должен быть хук, чтобы предоставить json.JSONEncoder для обработки этого.


Ответьте на это письмо напрямую или просмотрите его на GitHub.

К вашему сведению,

    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)

решает проблему в /mpld3/_display.py: fig_to_html

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

Я ожидал, что это будет исправлено PR # 213, но блокнот ipython из исходного поста у меня все еще не работает. Может еще кто попробует?

Я попробую это как-нибудь

Все еще сбит с толку этим ... Я не уверен, действительно ли # 213 что-то исправил здесь. Я могу сериализовать объекты int64 без него...

это было решено?
Кажется, я не могу fig_to_html сгенерировать фигуру, сгенерированную пандами (я получаю TypeError: 0 is not JSON serializable ). Фигура генерируется нормально.
Когда я повторил попытку с помощью plt.bar, я также получаю сообщение об ошибке, если использую yticks с пользовательскими строками.

Как решить?

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

Просто хотел указать, что я получаю эту ошибку при использовании

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

но не с

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

Надеюсь это поможет.

Редактировать: при дальнейшей проверке, хотя последняя версия не выдает ошибки, xticks результирующей фигуры фактически не устанавливаются.

Редактировать 2: Мой плохой, только что обнаруженные галочки не поддерживаются (# 22).

FWIW, использование блочных диаграмм может воспроизвести проблему:

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)

В частности, вот версии от заморозки пипса

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

для Python 3.4.3.

Патч, предложенный @lvasseur, кажется,

Чтобы исходный пример работал, используйте [float(x) for x in range(2000,2002)] вместо np.arange(2000,2002,1).

Не уверен, что это связано, но у меня возникает аналогичная проблема при попытке построить этот морской график: http://www.stanford.edu/~mwaskom/software/seaborn/examples/many_facets.html

Я получаю ту же ошибку при попытке mtld3.display(fig) для рисунка морского барплота:

TypeError: 0 не сериализуем JSON

Может ли кто-нибудь визуализировать морские сюжеты с помощью mpld3?

Кажется, это происходит из-за того, что в значениях данных есть nan . Если я сломаюсь на
и замените nan на None в figure_json dict, я получаю ожидаемый результат.

Редактировать: кажется, что выше проблема не решается (я тестировал в интерпретаторе отладки, где он работал, но не при использовании mpld3).
Итак, рендеринг sns.barplot() не работает, а рендеринг plt.bar() работает нормально. Я не увидел очевидной разницы в цифрах на обоих графиках, но предоставленный патч (https://github.com/mpld3/mpld3/pull/213) решил проблему.

Я исправил это, добавив строку

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

в /mpld3/_display.py: NumpyEncoder

Спасибо @jaklinger, это сработало!!!

@jaklinger , привет, спасибо за твое предложение, оно работает отлично! Я просто хотел уточнить одну вещь - я преобразовал массив numpy в словарь и попытался вернуть его, но он выдавал ошибку "float 32 не сериализуется json", хотя со словарем не было проблем, распечатал и проверил его. Просто с помощью вашего метода tolist() он преобразовал массив в список python.
предыдущая :[100. 0. 0. 0. 0.]
с tolist: [100.0, 0.0, 0.0, 0.0, 0.0], и он вернулся отлично.
Так в чем именно была проблема? Спасибо заранее.

@padmaksha18 Я не уверен на 100%, что ты имеешь в виду

преобразовал массив numpy в словарь

но (вкратце) типы numpy и python не совпадают ( float32 не совпадает с float ; array не совпадает с list и т. д.), а класс JSONEncoder «разрешает» только собственные типы python . Итак... смысл этой функции (которая содержит новое исправление) состоит в том, чтобы преобразовать входные данные obj в собственные эквиваленты python .

@jaklinger Привет, Джоэл, еще раз большое спасибо. Под преобразованием в словарь я просто имел в виду, что взял два таких массива и сформировал пару ключ-значение, извините, что не объяснил это ясно. Большое спасибо за то, что разъяснили мне эту вещь, я должен сначала преобразовать ее в собственный тип Python, и это было проблемой. Просто хотел прояснить еще одну вещь, например, если не jsonify словарь и попытаться вернуть его как есть, появится ли тогда класс jsonencoder? Большое спасибо!

pip установить "git+ https://github.com/javadba/mpld3@display_fix "

Была ли эта страница полезной?
0 / 5 - 0 рейтинги