У меня проблема с объектом Text, который используется matplotlib для представления меток.
По причине тестирования мне нужно проверить значение меток тиков, созданных на графике. Если метка является строкой или положительным числом, нет никаких проблем: возвращается строка юникода, я проверяю ее (или конвертирую ее в число, учитывая обстоятельства), и все в порядке.
Но если метка является отрицательным числом, то я вернусь - это искаженная строка юникода по той причине, которую я не могу понять.
Возьмем этот пример кода:
import pylab as plt
fig, ax = plt.subplots(1)
ax.plot([-1, 0, 1, 2], range(4))
labels = ax.get_xticklabels()
теперь, если я задаю текстовое содержимое второй метки (0
), я получаю нормальную строку юникода:
labels[1].get_text()
# u'0.0'
но юникод первого (-1
) - странная вещь
labels[1].get_text()
# u'\u22121'
Это правильно напечатано в терминале, но в этом случае мне нужно столкнуться с ним с числовым значением, и каждое преобразование завершится неудачно, как с int
, так и float
.
Я попытался преобразовать его в строку UTF-8 с помощью
text = labels[1].get_text()
text.encode('utf8')
# '\xe2\x88\x921'
но опять-таки это что-то, что правильно напечатано и вызывает ошибку при преобразовании. Я также посмотрел на модуль unicodedata
, но похоже, что он может конвертировать только один символ, поэтому в этом случае бесполезно. Я также попытался нормализовать строку с помощью unicodedata.normalize
и любого возможного формата, но опять же не удался.
Я перешел в модуль pipy unidecode
(как это предложено в Python и нормализация символов), без каких-либо успехов
from unidecode import unidecode
unidecode(text)
# '[?]1'
Я также пытался избежать проблем с шрифтами, используя решение в не-ASCII-символах в Matplotlib, но с тем же результатом (я не уверен, даже иметь что-то делать, будучи проблемой визуализации...). вопрос Акцентированные символы в Matplotlib имеет аналогичную проблему, поскольку он касается визуализации, а не самого значения
Я начинаю чувствовать себя немного потерянным... Я знаю, что у python 2.7 есть некоторая "трудность" юникода, но обычно я могу избежать их так или иначе.
Я знаю, что проблема - это знак минус, так как я могу избежать проблемы, используя грубую замену виновника:
text.replace(u'\u2212', '-')
# u'-1'
Но это больше и взломать, чем решение, и я почти уверен, что он не стабилен в разных системах, поэтому мне хотелось бы что-то ближе к решению.
Я работаю с
- python 2.7.3
- matplotlib 1.2.0
- pylab 1.7.0
- IPython 0.13.1
на Kubuntu 12.10.
Большое спасибо за вашу помощь!
EDIT:
Исправлен порядок сюжета, так как я получил перевернутый x и y, извините
EDIT2:
аналогичная информация присутствует по этой ссылке: http://www.coniferproductions.com/2012/12/17/unicode-character-dump-in-python/
в конце он показывает, как в некоторых книгах знак минус используется более эстетически приятным, но не распознанным интерпретатором python как допустимый символ.
EDIT3:
Загадка решена. персонаж, возвращающий matplotlib, является "МИНУС СИГНАЛОМ", т.е. правильным типографическим знаком для минуса. Тот, который создает keybord, фактически является "HYPHEN-MINUS", который обычно используется, но не является типографически правильным. см. в wikipedia для объяснения http://en.wikipedia.org/wiki/Hyphen-minus.
Итак, простая замена, которую я использовал, на самом деле является правильной практической задачей, но "этически" является ошибкой в python (2.7 и 3.x), которые не распознают правильный символ для знака минус.
см. отслеживание ошибок в http://bugs.python.org/issue6632
EDIT4:
чтобы отключить это поведение, есть простое решение на matplotlib, просто измените rcparams либо в .matplotlibrc, либо программно.
import matplotlib as mpl
mpl.rcParams['axes.unicode_minus']=False