转换unicode减号(来自matplotlib ticklabels)

Enr*_*eri 14 python string unicode matplotlib python-2.7

我遇到了matplotlib用来表示ticklabels的Text对象的问题.

出于测试原因,我需要检查在绘图中创建的刻度标签的值.如果标签是字符串或正数,则没有问题:返回一个unicode字符串,我测试它(或根据情况将其转换为数字),一切都很好.

但是如果标签是负数,我得到的是一个错误的unicode字符串,这是我无法理解的原因.

我们来看看这个示例代码:

import pylab as plt
fig, ax = plt.subplots(1)
ax.plot([-1, 0, 1, 2], range(4))
labels = ax.get_xticklabels()
Run Code Online (Sandbox Code Playgroud)

现在,如果我问第二个标签的文本内容(0),我获得了一个正常的unicode字符串:

labels[1].get_text()
# u'0.0'
Run Code Online (Sandbox Code Playgroud)

但是第一个(the -1)的unicode 是一个奇怪的事情

labels[1].get_text()
# u'\u22121'
Run Code Online (Sandbox Code Playgroud)

这是在终端中正确打印的,但在这种情况下,我需要用数值来对付它,并且每次转换都会失败,无论是intfloat.

我尝试将其转换为UTF-8字符串

text = labels[1].get_text()
text.encode('utf8')
# '\xe2\x88\x921'
Run Code Online (Sandbox Code Playgroud)

但同样,它是正确打印的东西,并在转换时引发错误.我也查看了unicodedata模块,但看起来它只能转换单个字符,所以在这种情况下是没用的.我也尝试使用unicodedata.normalize和任何可能的格式规范化字符串,但再次没有成功.

我移动到pipy模块unidecode(如Python和字符规范化中所建议的那样),再次没有任何成功

from unidecode import unidecode
unidecode(text)
# '[?]1'
Run Code Online (Sandbox Code Playgroud)

我也试图在Matplotlib中使用非ASCII字符的解决方案来避免字体问题,但结果相同(我不确定它是否应该做些什么,这是一个可视化的问题......).问题Matplotlib中的Accented字符有一个类似的问题,因为它关注的是可视化而不是它本身的价值

我开始觉得有点迷失......我知道python 2.7有一些unicode"难度",但通常我可以用某种方式避免它们.

我知道问题是减号,因为我可以通过粗暴的替代罪魁祸首来避免这个问题:

text.replace(u'\u2212', '-')
# u'-1'
Run Code Online (Sandbox Code Playgroud)

但这比解决方案更多,更黑,而且我几乎可以肯定它在不同的系统中并不稳定,所以我希望更接近解决方案.

我正在和我一起工作

  • python 2.7.3
  • matplotlib 1.2.0
  • pylab 1.7.0
  • IPython 0.13.1

在Kubuntu 12.10上.

非常感谢您的帮助!

编辑:

纠正了情节的顺序,因为我得到了x和y倒置,抱歉

EDIT2:

此链接中包含类似信息:http://www.coniferproductions.com/2012/12/17/unicode-character-dump-in-python/

最后它显示了在某些书籍中使用的减号是一个更令人愉快的减号,但是python解释器没有将其识别为有效字符.

EDIT3:

谜语解决了.matplotlib返回的字符是"MINUS SIGN",即减号的正确标记符号.键盘创建的那个实际上是"HYPHEN-MINUS",这是常用的但不是典型的正确.在维基百科上查看http://en.wikipedia.org/wiki/Hyphen-minus的解释.

所以,我使用的简单替换实际上是正确的实际操作,但"道德上"是python(2.7和3.x等)中的一个错误,它不能识别减号的正确符号.

请参阅http://bugs.python.org/issue6632中的错误跟踪

EDIT4:

要禁用此行为,matplotlib上有一个简单的解决方案,只需在.matplotlibrc中或以编程方式修改rcparams即可.

import matplotlib as mpl
mpl.rcParams['axes.unicode_minus']=False
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 1

所有有效的 unicode 字符都有名称。我们可以检查可识别数字单词 ( ) 的名称DIGIT.keys(),并在此基础上用DIGIT.values()给定的 unicode 标签替换“正常”数字字符 ( ):

import matplotlib.pyplot as plt
import unicodedata as UD

DIGIT = {
    'MINUS': u'-',
    'ZERO': u'0',
    'ONE': u'1',
    'TWO': u'2',
    'THREE': u'3',
    'FOUR': u'4',
    'FIVE': u'5',
    'SIX': u'6',
    'SEVEN': u'7',
    'EIGHT': u'8',
    'NINE': u'9',
    'STOP': u'.'
    }

def guess(unistr):
    return ''.join([value for u in unistr
                    for key,value in DIGIT.iteritems()
                    if key in UD.name(u)])

fig, ax = plt.subplots(1)
ax.plot([-1, 0, 1, 2], range(4))
plt.savefig('/tmp/test.png')
labels = ax.get_xticklabels()
for label in labels:
    label = label.get_text()
    print(guess(label))
Run Code Online (Sandbox Code Playgroud)

产量

-1.0
-0.5
0.0
0.5
1.0
1.5
2.0
Run Code Online (Sandbox Code Playgroud)