14

matplotlibがティックラベルを表すために使用するTextオブジェクトに問題があります。

テスト上の理由から、プロットで作成された目盛りラベルの値を確認する必要があります。ラベルが文字列または正の数の場合、問題はありません。Unicode文字列が返され、テスト(または状況に応じて数値に変換)すると、すべて問題ありません。

しかし、ラベルが負の数である場合、私が返すのは、理解できない理由で壊れたユニコード文字列です。

このサンプルコードを見てみましょう:

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

ここで、2番目のラベル()のテキストコンテンツを尋ねると0、通常のUnicode文字列が得られます。

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'

しかし、これも正しく印刷され、変換時にエラーが発生するものです。モジュールも調べましたが、unicodedata1文字しか変換できないようですので、この場合はダメです。unicodedata.normalize文字列を可能な形式で正規化しようとしましたが、やはり成功しませんでした。

私はpipyモジュールに移動しました( Pythonと文字の正規化unidecodeで提案されているように)、これも成功しませんでした

from unidecode import unidecode
unidecode(text)
# '[?]1'

Matplotlibの非ASCII文字のソリューションを使用してフォントの問題を回避しようとしましたが、同じ結果になりました(視覚化の問題であるため、何かする必要があるかどうかはわかりません...)。質問Matplotlibのアクセント付き文字にも同様の問題があります。これは、値自体ではなく視覚化に関係しているためです。

少し迷い始めています...Python2.7にはユニコードの「難しさ」があることは知っていますが、通常は何らかの方法でそれらを回避できます。

犯人の残忍な置き換えを使用して問題を回避できるため、問題がマイナス記号であることを私は知っています。

text.replace(u'\u2212', '-')
# u'-1'

しかし、これは解決策よりもハックであり、さまざまなシステム間で安定していないことはほぼ確実なので、解決策に近いものが必要です。

私は一緒に働いています

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

Kubuntu12.10で。

ご助力ありがとうございます!

編集:

xとyを反転させたので、プロットの順序を修正しました。申し訳ありません。

EDIT2:

同様の情報がこのリンクにあります:http://www.coniferproductions.com/2012/12/17/unicode-character-dump-in-python/

最後に、一部の本で使用されているマイナス記号が、よりエステティックに心地よいものであるが、Pythonインタープリターによって有効な文字として認識されていないことを示しています。

EDIT3:

なぞなぞは解決しました。matplotlibが返す文字は、「マイナス記号」、つまりマイナスの正しいタイプミス記号です。キーボードが作成するものは、実際には「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
4

2 に答える 2

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

収量

-1.0
-0.5
0.0
0.5
1.0
1.5
2.0
于 2013-03-21T10:17:49.167 に答える
1

plt.xticks()の代わりに使用ax.get_xticklabels():

import matplotlib.pyplot as plt

fig, ax = plt.subplots(1)
ax.plot([-1, 0, 1, 2], range(4))
plt.savefig('/tmp/test.png')
loc, labels = plt.xticks()
print(type(loc))
# <type 'numpy.ndarray'>
print(loc)
# [-1.  -0.5  0.   0.5  1.   1.5  2. ]
于 2013-03-21T02:50:32.987 に答える