たとえば、こんな感じの表があったとするじゃないですか。
店 | うし | ぶた | とり |
---|---|---|---|
肉屋 | 580 | 280 | 300 |
スーパー | 420 | 260 | 320 |
これを、エクセルに入力して、挿入->3D-縦棒と選ぶと
こんな感じのかっこいい(?)グラフが作れるわけですが、これをpandas+matplotlibでやってみようというお話です。
結論から先に書くと
import pandas as pd import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib.font_manager import FontProperties df=pd.DataFrame({u"うし":[580, 420], u"とり":[280, 260], u"ぶた":[300, 320]}, index=(u"肉屋", u"スーパー")) ax=plt.figure().add_subplot(111, projection='3d') fp=FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=10) xpos,ypos=np.meshgrid(np.arange(len(df.index)), np.arange(len(df.columns))) xpos=xpos.flatten() ypos=ypos.flatten() zpos=np.zeros(len(xpos)) dx=np.full(len(xpos), 0.05) dy=np.full(len(ypos), 0.1) dz=df.as_matrix().flatten() ax.bar3d(xpos, ypos, zpos, dx, dy, dz) ax.set_xlabel(u"お店", fontproperties=fp) ax.set_ylabel(u"種類", fontproperties=fp) ax.set_zlabel(u"金額", fontproperties=fp) plt.xticks(np.arange(len(df.index)), df.index, fontproperties=fp) plt.yticks(np.arange(len(df.columns)), df.columns, fontproperties=fp) plt.axis([-0.5, len(df.index)-0.5, -0.5, len(df.columns)-0.5]) plt.savefig("hoge.png")
みたいなコードになります。
公式ページのexampleを見ると、
mplot3d example code: bars3d_demo.py — Matplotlib 1.4.3 documentation
ってのがありますが、こっちは普通の棒グラフを奥行方向に重ねて並べるもののようで、今回作ろうと思っていたのとはちょっと違います。
一見関係無さそうな名前ですが、
mplot3d example code: hist3d_demo.py — Matplotlib 1.4.3 documentation
のところで使っている、bar3d()が今回のグラフに必要な関数でした。
ところがこの関数、APIドキュメントがこんな調子でまったく意味不明です。
bar3d(x, y, z, dx, dy, dz, color=u'b', zsort=u'average', *args, **kwargs)
Generate a 3D bar, or multiple bars.
When generating multiple bars, x, y, z have to be arrays. dx, dy, dz can be arrays or scalars.
color can be:
A single color value, to color all bars the same color.
An array of colors of length N bars, to color each bar independently.
An array of colors of length 6, to color the faces of the bars similarly.
An array of colors of length 6 * N bars, to color each face independently.When coloring the faces of the boxes specifically, this is the order of the coloring:
-Z (bottom of box)
+Z (top of box)
-Y
+Y
-X
+XKeyword arguments are passed onto Poly3DCollection()
http://matplotlib.org/mpl_toolkits/mplot3d/api.html#mpl_toolkits.mplot3d.axes3d.Axes3D.bar3d
x, y, z have to be arraysとか言われても、何の値入れりゃえんじゃーと悩んでましたが、どうやら
- 各配列は全て同じ長さの1次元配列にする
- i番目の棒の左下隅の頂点座標をx, y, zのi番目の要素で指定
- i番目の棒の各軸方向の幅をdx, dy, dzのi番目の要素で指定
ということのようです。
ちなみに、この例ではx、yともに項目名なのであまり違和感は無いかもしれませんが、元々私がやってた時は2次元でパラメータを振った時の実験結果をプロットしようとしていたので、x, y, zに値を入れてからdx, dy, dzって何を入れるんだろうかと、かなりドツボにはまってました。*1
あとのところは、コードを見れば分かると思いますので、解説は省きますが
- set_?label
- ラベルの設定
- {x,y}ticks
- x/y座標の値の指定
- axis
- 座標軸の長さ指定
- savefig
- グラフを画像ファイルとして保存
です。
matplotlibの全般的な話は
matplotlib入門 - りんごがでている
に助けられました。ここ読まなかったら未だドキュメントの海で溺れてたと思いますorz
あと、フォント関連の設定については
Python - matplotlibで日本語 - Qiita
を参考にさせていただきました。
そういや、pandasろくに使って無いな・・・