Pythonって、量子システムからコールセンターのトラフィック分析まで、マジで何でもシミュレーションしたり計算したりできる。でも、意外と見過ごされがちなのが「数式をどうやってキレイに見せるか」って問題。うん、僕も最初は気にしてなかった。
でもね、例えばアーランC式みたいな、ちょっと複雑な数式を誰かに説明しなきゃいけない場面を想像してみてほしい。ただ計算結果を出すだけじゃなくて、その数式自体をプレゼン資料とか、技術ブログとかで共有したいとき、ただのテキストじゃ、もう何が何だか分からないんだよね。
こういうのを実現するのが、LaTeX(ラテック、あるいはラテフ)風の数式描画。Pythonネイティブの機能じゃないんだけど、助けてくれるライブラリがいくつかある。今日は、僕がよく使う、あるいは「こういう時はこれだよね」って思う選択肢を、ちょっと語ってみようかなと思う。
一番手軽なのは、やっぱりMatplotlib
はい、まずは定番から。Matplotlib。グラフ描画のライブラリとして知られてるけど、実はタイトルとか軸ラベルに数式を入れる機能が標準でついてる。これが結構便利。
使い方は超簡単で、表示したい数式の文字列を `$`(ドルマーク)で囲むだけ。これだけで、Matplotlibが頑張って解釈してくれる。
import matplotlib.pyplot as plt
# ちょっと大きめの画像を用意して...
plt.figure(figsize=(10, 4), dpi=120)
# r'' を使って、バックスラッシュをエスケープさせないのがコツ
formula_text = r'$P_w = \frac{\frac{A^N}{N!} \cdot \frac{N}{N - A}}{\left( \sum_{i=0}^{N-1} \frac{A^i}{i!} \right) + \frac{A^N}{N!} \cdot \frac{N}{N - A}}$'
# text() で好きな位置に数式をポンと置く
plt.text(0.1, 0.5, formula_text, fontsize=20)
# 軸とか枠線は要らないから消しちゃう
plt.axis('off')
plt.show()
ほら、これだけでさっきみたいな数式の画像が作れる。グラフの中に注釈として数式を入れたいときなんかは、これが一番早い。ただ、複数行にわたる複雑な行列とか、もっとレイアウトを細かく調整したいってなると、途端に面倒くさくなるのが玉にキズかな。
計算も表示もやりたいならSymPy
次にSymPy。これはPythonの記号計算ライブラリ。つまり、`x + x` を `2x` って計算してくれるようなやつ。で、こいつは計算するだけじゃなくて、その過程や結果の数式を「見せる」のも得意。
SymPyのいいところは、Pythonのオブジェクトとして数式を組み立てられること。文字列としてLaTeXコードをベタ書きするんじゃなくて、もっとプログラマティックに扱える。
from sympy import symbols, factorial, Sum, Eq, pprint
from sympy.abc import A, N, i # AとかNを記号として使えるようにする
# 分子と分母をそれぞれPythonのコードで組み立てていく
numerator = (A**N / factorial(N)) * (N / (N - A))
denominator = Sum(A**i / factorial(i), (i, 0, N-1)) + numerator
# Eqで方程式の形にする
formula = Eq(symbols('P_w'), numerator / denominator)
# pprintを使うと、ターミナル上でそれっぽく表示してくれる
pprint(formula, use_unicode=True)
ターミナルで `pprint` すると、テキストベースだけどかなり読みやすい形で表示される。デバッグしながら「今、数式の形どうなってるっけ?」って確認するのにすごく便利。…あ、ちなみにJupyter Notebookみたいな環境ならもっときれいに表示される。それは後で話すね。
それに、SymPyオブジェクトを `latex()` 関数に渡せば、そのままWebページとかで使えるLaTeXコードを吐き出してくれる。地味にこれが一番使う機能かもしれない。
from sympy import latex
# さっき作ったformulaオブジェクトを渡すだけ
latex_code = latex(formula)
print(latex_code)
# 出力: P_{w} = \frac{\frac{A^{N}}{N!} \cdot \frac{N}{N - A}}{\sum_{i=0}^{N - 1} \frac{A^{i}}{i!} + \frac{A^{N}}{N!} \cdot \frac{N}{N - A}}
この文字列をコピーして、後述するMathJaxとかKaTeXを使ってるWebページに貼り付ければ、もう綺麗な数式の出来上がり。便利。
Jupyter Notebook使ってるなら、もう勝ち組
もし君がデータ分析とかでJupyter Notebook(またはJupyterLab)を使ってるなら、もう何も悩むことはないかもしれない。Jupyterは内部でMathJaxっていうJavaScriptライブラリを動かしてて、LaTeX形式の文字列を自動で美しい数式にレンダリングしてくれるから。
特にSymPyとの連携は最高。`init_printing()` っておまじないを最初に実行しておくだけで、SymPyの数式オブジェクトをセルの最後に置くと、勝手に綺麗な数式として表示される。
from sympy import init_printing
init_printing() # これがおまじない
# さっきと同じformulaオブジェクトをdisplay()するか、セルの最後に置くだけ
display(formula)
あるいは、Markdownセルで直接LaTeXコードを書くこともできる。これも `$` や `$$` で囲むだけ。技術的なメモを取りながら、コードを書いて、結果を数式で確認して…っていう一連の流れがシームレスにできる。教育用途とか、自分の思考過程を記録するには最強の環境だと思う。
動画やガチのプレゼンならManim
ここからはちょっと玄人向け。Manimっていうのは、YouTubeの有名な数学チャンネル「3Blue1Brown」の運営者が作った、数式アニメーションエンジン。そう、あの数式が動いたり変形したりするやつ。
正直、これは「ちょっと数式を表示したい」っていうレベルのツールじゃない。本気で教材ビデオを作りたいとか、プレゼンテーションで聴衆の度肝を抜きたい、っていう人向け。環境構築も結構大変。
Manimは裏側でフルセットのLaTeXを使ってるから、表現力はピカイチ。でも、そのためには自分のPCにLaTeX環境そのものとか、動画生成のためのFFmpegとかをインストールしなきゃいけない。僕も最初、Windowsでパスがうまく通らなくて半日溶かした経験がある…。日本のQiitaとかだとまだ情報が少ないから、基本は海外のManim Communityのドキュメントと格闘することになるかな。
from manim import Scene, MathTex
class ErlangCScene(Scene):
def construct(self):
# MathTexにLaTeXコードを渡す
formula = MathTex(
r"P_w = \frac{\frac{A^N}{N!} \cdot \frac{N}{N - A}}{\left( \sum_{i=0}^{N-1} \frac{A^i}{i!} \right) + \frac{A^N}{N!} \cdot \frac{N}{N - A}}"
).scale(1.2) # ちょっと大きくする
self.play(Write(formula)) # アニメーションで表示
self.wait(2)
これを実行すると、数式が描画されるアニメーションのMP4ファイルが出来上がる。静止画が欲しいだけなら、最後のフレームを画像として保存することもできるけど、まあ、そのためだけにManimを使うのは大げさだよね。
結局どれを使えばいいの? 用途別まとめ
ここまで色々見てきたけど、結局「これが一番!」っていうのはない。完全に「何がしたいか」による。僕なりにまとめてみると、こんな感じかな。
| ライブラリ | こういう時にオススメ | 注意点とか「ここはイマイチ」な所 |
|---|---|---|
| Matplotlib | グラフにちょっと数式を添えたい時。論文用の静止画プロットとか。 | 複雑なレイアウトは苦手。あくまで「テキスト」機能のおまけって感じ。 |
| SymPy | 計算過程を記号で追いかけたい時。ターミナルでのデバッグとか。 | これ単体では画像は作れない。あくまで計算とLaTeXコード生成がメイン。 |
| Jupyter + MathJax | データ分析のメモ、教育コンテンツ、ブログの下書き。試行錯誤に最高。 | ブラウザベースだから、デスクトップアプリへの組み込みとかには向かない。 |
| Manim | 数学の解説動画を作りたい!プレゼンで差をつけたい!っていう本気の人。 | 環境構築がマジで大変。気軽に試すと心折れるかも。学習コストも高い。 |
| KaTeX (Web) | Flask/Djangoで作ったWebアプリで高速に数式表示したい時。 | MathJaxより少しマイナーなLaTeXコマンドには非対応だったりする。でも速い。 | tr>
あ、最後のKaTeXは、Web系の人向けかな。FlaskとかFastAPIでPythonのバックエンドを書いて、フロントエンドのHTMLで数式を表示させたいって時に、MathJaxの代わりに使えるJavaScriptライブラリ。MathJaxよりレンダリングが速いのが売り。でもこの話は長くなるから、また別の機会に。
重点一句話
要するに、グラフに添えるならMatplotlib、試行錯誤しながらメモるならJupyter、Webで公開するならSymPyでLaTeXコードを生成してKaTeX/MathJaxに渡す、ってのが現実的な使い分けだと思う。Manimは…まあ、ロマン枠だね。
というわけで、Pythonで数式を扱う方法をいくつか紹介してみたけど、どうだったかな。自分のプロジェクトで「これ使ってみようかな」って思ったものはあった? もし他にも面白いライブラリとかテクニックを知ってたら、ぜひ教えてほしい。
