matplotlibで円グラフを書く

タイトル通りだが、実際にやってみると幾つかうまく行かないところがあったのでメモ。

そもそも円グラフを書くには

plot.pie あるいは axes.pie関数を利用する。

http://matplotlib.org/examples/pie_and_polar_charts/pie_demo_features.html


データの描画順序と開始位置

何も指定しない場合は反時計回りにデータが描かれていく(上記のサンプルも参照)。

今回の場合、円の一番上を初期基準として時計回りにデータを描画したかったのでpie関数のcounterclockをFalseに、startangleを90に指定して描画を実施した。

ただし、これらの導入が実施されたのがmatplotlibのver1.4.0以降であり、Ubuntuのapt-getで入れようとすると1.3.1しか入らなかったのでpipを使って最新のものを入れなおす必要がある。

…が、必要なライブラリが足りないと怒られるので、以下のページを参考にして必要なlibを入れる。

http://stackoverflow.com/questions/20533426/ubuntu-running-pip-install-gives-error-the-following-required-packages-can-no


自分の環境では以下のライブラリをインストールすれば成功した。

sudo apt-get install libfreetype6-dev libxft-dev
sudo pip install matplotlib

フォントを変えたい場合

labelsパラメータを指定すると、legend(グラフの近くに表示される軸の名前みたいなやつ)に表示する情報を渡してくれるが、グラフの上にもきっちりと書き込んでくれる。

これを非表示にして、legendだけを表示したいというのが今回やりたかった。

実現方法としては、pieの戻り値の第2引数で描画を実施する予定のTextオブジェクトを返してくれるので、これらを非表示にすればできた。
fontsizeの変更などもここで処理すれば同様に可能。

全部まとめて

Python2.7 + matplotlib1.4.3で動作を確認。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

filename = 'circle.png'

# 500px x 300px の画像を生成
fig = plt.figure(figsize=(5, 3), dpi=100)
ax = fig.add_subplot(1, 1, 1)

# これが無いと楕円になる
ax.set_aspect('equal')

data = [777, 456, 234, 123]
labels = ['Hoge', 'Piyo', 'Fuga', 'Hogera']
colors = ['r', 'y', 'g', 'b']

# 10%以下の比率の場合はパーセントを表示しない
(_, texts, autotexts) = ax.pie(data, colors=colors, labels=labels,
    startangle=90, counterclock=False,
    autopct=lambda p: '{:.1f}%'.format(p) if p >= 10 else '')
for text in texts:
  text.set_visible(False)

# 座標はfigsizeの比率によって微調整が必要
box = ax.get_position()
ax.set_position([-0.08, box.y0, box.width, box.height])
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size': 12})

fig.savefig(filename)
plt.close(fig)

もっと詳しくはpie関数のリファレンスを読んで下さい。

http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.pie