2018年04月18日

言語処理100本ノックでPython入門 #37 - matplotlibで棒グラフ作成

  
言語処理100本ノック 2015の問題37に挑戦です。

■ 問題
夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ. なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.

37. 頻度上位10語
出現頻度が高い10語とその出現頻度をグラフ(例えば棒グラフなど)で表示せよ.


■ Pythonのコード
import re
import matplotlib.pyplot as plt

def analyze():
    lines = []
    sentence = []
    with open('neko.txt.mecab', 'r', encoding='utf8') as fin:
        for line in fin:
            words = re.split(r'\t|,|\n', line)
            if words[0] == 'EOS':
                if sentence:
                    lines.append(sentence)
                    sentence = []
                continue
            sentence.append({
                "surface": words[0],
                "base": words[7],
                "pos": words[1],
                "pos1": words[2],
            })
    return lines

def getFrequency(lines):
    words = {}
    for sentense in lines:
        for word in sentense:
            if word['pos'] == '記号':
                continue
            if word['surface'] in words.keys():
                words[word['surface']] += 1
            else:
                words[word['surface']] = 1
    return words

def plotBarChart(sortedwords):
    categories = [x[0] for x in sortedwords]
    xaxis = [x for x in range(10)]
    values = [x[1] for x in sortedwords]

    #plt.rcParams['font.family'] = 'AppleGothic' 
    plt.rcParams['font.family'] = 'Meiryo' 

    plt.bar(xaxis, values)
    plt.xticks(xaxis, categories)
    plt.show()

def main():
    article = analyze()
    words = getFrequency(article)
    sortedwords = sorted(words.items(), key=lambda x: x[1], reverse=True)[0:10]
    print(sortedwords)
    plotBarChart(sortedwords)

if __name__ == '__main__':
    main() 

■ matplotlib.pyplotを使う


まずは、anacondaのcondaコマンドを使って、macに、matplotlibをインストールします。
$ conda install matplotlib

インストールしている途中で、以下のメッセージが出てきたので、y を押します
The following packages will be UPDATED:

    anaconda:   4.3.1-np111py36_0 --> custom-py36_0
    conda:      4.3.14-py36_0     --> 4.3.30-py36h173c244_0
    matplotlib: 2.0.0-np111py36_0 --> 2.0.2-np111py36_0

Proceed ([y]/n)? y

無事インストールできたので、matplotlib.pyplotをimportします。
    import matplotlib.pyplot as plt
これで、pltという名前で利用できるようになります。

実際にグラフを書いているのはplotBarChartメソッド内です。barメソッドでチャートを描いています。 

初めは、以下のように書いてみました。
categories = [x[0] for x in sortedwords]
xaxis = [x for x in range(10)]
values = [x[1] for x in sortedwords]

plt.bar(xaxis, values)
plt.xticks(xaxis, categories)
plt.show()
でも、日本語が文字化けしてしまいます。


■ matplotlibの文字化け対応

matplotlibの環境設定でフォントを日本語にするという方法もあるようですが、ここではコードだけで対応することにします。

まず、
import matplotlib.font_manager as fm
print([f.name for f in fm.fontManager.ttflist])
で、matplotlib利用できるフォント一覧を表示してみます。

僕の環境では’Meiryo’フォントがありますのでこれを使います。 たぶん、Microsoft Officeをインストールしているからかな。
そのほか、AppleGothicというフォントも日本語が表示できるようです。

メイリオフォントが使えることがわかったので、以下のように1行追加するだけで、日本語化することができました。
plt.rcParams['font.family'] =  ‘Meiryo’  // これを追加

plt.bar(xaxis, values)
plt.xticks(xaxis, categories)
plt.show()

どこまで、見た目をカスタマイズできるのかわからないけど、簡単にグラフが書けるのは便利ですね。


■ 結果
nlp37


出現頻度が高い10語とその出現頻度をコンソールにも表示しています。
[('の', 9194), ('て', 6868), ('は', 6420), ('に', 6243), ('を', 6071), ('と', 5508), ('が', 5337), ('た', 3988), ('で', 3806), ('も', 2479)]