Matplotlibで経済学の図を描く:需要と供給

一番はじめの図

Matplotlibでさくっと経済学の図が書けたら、楽なはずだ。

PowerPointで図を書いているときに、「ここが塗りたいのに、ずれた!」的なことはよくある。 根性で書いてもよいが、毎回根性が必要となると、萎えてくる。

実は僕自身はけっこう、PowerPointの扱いに慣れていて、図もかなりのスピードで作図できるようになっている。

けれども、出先などでマウスがないときに、タッチパッドで図を書くのは嫌だ。

似たような図なんだけど、ちょっとだけ平行移動したいときは、線の長さが変わるのでけっこうめんどうだ。

などなど、細かなストレスがある。

じゃあ、エクセルは?とも思うのだが、塗りつぶしの手間を考えるとあまり手を出す気はしない。

来年、一冊本を書くことになったので、この際、スクリプトで書けたらいいなあと感じはじめた。 論文の図もきれいなのが、書けるようになるだろうし、なにより推定結果から再現可能な図を作れるようになれば、かなり助かる。

というわけで、この際、作図をマスターすることにした。

作図環境

作図はPython+Matplotlibだ。 中期的にはPython+Plotnineに移行するが、今は標準環境をマスターする。

ちなみに、JavaScpriptを使って動く図を使うような環境も作れるが、僕はそちらにはあまり関心がない。 授業でも図を動かすときは、基本の図を作って、そこにペンで書きこんでいる。

(リアルなペンではなく、スタイラスでパワポ上に線を描画してるだけやけどね)

さて、まずは簡単な図

経済学の基本的な講義でほんとに毎回というぐらい使用するのが、需要と供給のごくシンプルな図。 僕は、どんな説明も最終的には、できるだけこの図に落としこむようにしているので、毎回使う。

https://blog.ecofirm.com/images/econfig001.png

この図は、抽象的な需要と供給なので、横軸と縦軸の目盛りがいらない。 単に右上がりの線と右下がりの線があればよい。

だが、これが意外と難しい。 抽象的に線がひければいいと思っているから、座標はいらないのかな?と感じてしまうと、もうそこから進まない。

Matplotlibのばあい、座標が必要だ。

なので、xを0から100の範囲と定義してその間で線をひくようにしてやる。

そのためには、x=np.linspace(0,100,101)とする。これは、xを0から100の間で定義して、その間を101個に区切るという命令だ。 100個ではなく101個なのは、0もカウントされるからだ。 この命令で、xには、0から100までの整数が格納される。 なお、0から100である必要もなくて、0から20とか0から10でもかまわない。

単純な直線を引くだけなら、ここは別に0と100だけでもいいし、整数でなくてもいいので30とかにしても問題ない。 曲線を書いたり、交点の座標を表示させたりすることを考えるなら、むしろ10000ぐらいにしておいたほうがいいが、まあ、今はどうでもいい。

この程度の作図なら、区切りが多くてもパフォーマンスにはほとんど影響しない。

この基本図でじゃまになるのが、目盛りだ。縦軸と横軸の数字は不要だ。 set_xticksとset_yticksを定義して、X軸の0として原点のみ表示させている。

また、あまり枠のなかに、きつきつに直線が入るのも好みではないので、右側と上に20ずつ余裕をもたせている。

もう一点、周囲の枠は不要で、X軸とY軸の線だけを表示させるために、右と上の線は消している。

ここまででようやく、枠の準備ができた。

次に需給曲線を引く。 これは、y=xとy=100-xを引くだけだ。

これで基本的な需要供給の図は完成だ。

こまごまとした装飾も可能だが、それは次回以降にとりくむ。

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('Agg')
#matplotlib.use('tkagg')

x = np.linspace(0,100,101)

myfig = plt.figure()
ax1 = myfig.add_subplot(111)

ax1.set_xticks(ticks=[0])
ax1.set_yticks(ticks=[])
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_xlim(0,120)
ax1.set_ylim(0,120)
ax1.spines['right'].set_visible(False)
ax1.spines['top'].set_visible(False)

ax1.plot(x,x)
ax1.plot(x,100-x)
myfig.savefig('images/econfig001.png')

plt.close(myfig)
Hugo で構築されています。
テーマ StackJimmy によって設計されています。