nltk.FreqDist および nltk.ConditionalFreqDist の plot() で日本語を出力させる方法

nltk.FreqDist クラスおよび nltk.ConditionalFreqDist クラスに含まれる plot() メソッドを利用した場合,軸(特に横軸)で日本語フォントが使えないという問題がある。
plot() メソッドでは内部的に matplotlib.pyplot を利用しており,日本語を出力するためには fontproperties を明示的に指定する必要がある。

以上の事情を踏まえ,nltk 自体に手を入れる。

対象とするファイル:
/usr/local/lib/python2.7/dist-packages/nltk/probability.py

probability.py 内の class FreqDist および class ConditionalFreqDist それぞれに
含まれる plot() メソッドを次のように書き換える。pylab.xticks() におけるパラメータ fontproperties の指定が肝である。
なお,フォント名は各自の環境に応じて変更すること。
(FreqDist クラスのみ示す。ConditionalFreqDist も同様に。)

def plot(self, *args, **kwargs):
    try:
        import pylab
    except ImportError:
        raise ValueError('The plot function requires the matplotlib package (aka pylab).'
                         'See http://matplotlib.sourceforge.net/')

    # code added : 2012.12.27 (from here)
    import sys
    import matplotlib.font_manager

    reload(sys)
    sys.setdefaultencoding('utf-8')
    fontprop = matplotlib.font_manager.FontProperties(fname='/usr/share/fonts/opentype/ipafont-gothic/ipag.ttf')
    # code added : 2012.12.27 (up to here)

    if len(args) == 0:
        args = [len(self)]
    samples = list(islice(self, *args))
        
    cumulative = _get_kwarg(kwargs, 'cumulative', False)
    if cumulative:
        freqs = list(self._cumulative_frequencies(samples))
        ylabel = "Cumulative Counts"
    else:
        freqs = [self[sample] for sample in samples]
        ylabel = "Counts"
    # percents = [f * 100 for f in freqs]  only in ProbDist?
        
    pylab.grid(True, color="silver")
    if not "linewidth" in kwargs:
        kwargs["linewidth"] = 2
    if "title" in kwargs:
        pylab.title(kwargs["title"])
        del kwargs["title"]
    pylab.plot(freqs, **kwargs)
    # code changed : 2012.12.27
    #pylab.xticks(range(len(samples)), [str(s) for s in samples], rotation=90)
    pylab.xticks(range(len(samples)), [str(s).decode('utf-8') for s in samples], rotation=90, fontproperties=fontprop)

    pylab.xlabel("Samples")
    pylab.ylabel(ylabel)
    pylab.show()

最後に probability.py をコンパイルして,準備完了。

$ cd /usr/local/lib/python2.7/dist-packages/nltk/
$ sudo python -m compileall probability.py

conditionalFreqDist.plot() を実行した結果を以下に示す。
f:id:ymuto109:20121227133926p:plain