導入
latexでレポートを書いている時にふと思いました。グラフと本文フォント揃ってないじゃん。どうやって揃えよう。
そんな話です
私は今グラフを作るときはpythonを使っています。
初めはexcel使いづらすぎだろと思ってpythonを使ってみました。
今ではもはやpythonの方が明らかに使いやすいと思っています。
毎回設定変えなくてもいいし。
フォントも揃うし。
excelよくわかんないし
みんなもpython使おうね
環境
- python
- lualatex
レポートの本文をlualatexで書いてグラフをpythonで作ります。
lualatexを使っていることを前提に話を進めていきます。
今日の方法だとpythonからlualatexを呼び出すことにもなりますが。
使うpythonのライブラリはmatplotlib,numpy,scipyです。
余談
データベースとしては私もexcelを使っています。
レポートを書くときはexcelからデータを読み取るためにopenpyxlを使っています。
やり方
matplotlib,scipyの基本を学んでから、レーポートにも使えるグラフを作っていきましょう。
準備
まずはscipyを使って近似直線を求める方法と、matplotlibを使って基本的なグラフを作る方法を覚えましょう。
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
def main():
# サンプルデータの生成
x_data = np.arange(100)
y_data = x_data + np.random.normal(0, 2, size=x_data.shape)
# データのフィッティング
params, _ = curve_fit(linear_model, x_data, y_data)
a, b = params
print(f"Fitted parameters: a = {a}, b = {b}")
# 決定係数R²の計算
y_pred = a * x_data + b
ss_res = np.sum((y_data - y_pred) ** 2)
ss_tot = np.sum((y_data - np.mean(y_data)) ** 2)
r2 = 1.0 - ss_res / ss_tot if ss_tot != 0 else 0.0
print(f"R²: {r2:.4f}")
# プロットの作成
x_min = np.min(x_data)
x_max = np.max(x_data)
x_range = np.linspace(x_min, x_max, 100)
y_fit = a * x_range + b
# グラフの描画
fig, ax = plt.subplots()
ax.scatter(x_data, y_data, label="Data Points")
ax.plot(x_range, y_fit, label="Fitted Line")
ax.legend()
ax.set_title("Simple Line Plot")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.minorticks_on()
save_path = "sample.png"
fig.savefig(save_path, dpi=300, bbox_inches="tight")
plt.show()
def linear_model(x, a, b):
"""1次関数モデル(y = ax + b)"""
return x * a + b
データから最小二乗法で近似直線を求めた後グラフを生成し、保存するプログラムです。
ちなみにmatplotlibは何も設定しなくても簡単なtexが使えるので
ax.set_title(r"$\frac{4}{\pi}$")
なども使えます。ただし、このままだと日本語が文字化けするので注意。
本格的なグラフの生成。
まずtexファイルを用意します。
\documentclass[a4paper,fontsize=10pt]{jlreq}
\usepackage{fontspec}
\usepackage{unicode-math}
\usepackage{luatexja-fontspec}
\setmainfont[
Path = /absolute/path/to/fontdir/,
UprightFont = STIXTwoText-Regular.ttf,
ItalicFont = STIXTwoText-Italic.ttf,
BoldFont = STIXTwoText-Bold.ttf,
BoldItalicFont = STIXTwoText-BoldItalic.ttf
]{STIX Two Text}
\setsansfont[
Path = /absolute/path/to/fontdir/,
UprightFont = NotoSans-Regular.ttf,
ItalicFont = NotoSans-Italic.ttf,
BoldFont = NotoSans-Bold.ttf,
BoldItalicFont = NotoSans-BoldItalic.ttf
]{Noto Sans}
\setmathfont{STIX Two Math Regular}
\setmainjfont[
Path = /absolute/path/to/fontdir/,
UprightFont = NotoSerifJP-Regular.ttf,
BoldFont = NotoSerifJP-Bold.ttf
]{Noto Serif JP}
\setsansjfont[
Path = /absolute/path/to/fontdir/,
UprightFont = NotoSansJP-Regular.ttf,
BoldFont = NotoSansJP-Bold.ttf
]{Noto Sans JP}
\title{テスト}
\author{Kuma}
\date{\today}
\begin{document}
\maketitle
Hello, World!
こんにちは,世界!\\
\textrm{Roman ローマン体}\\
\textbf{Boldface 太字}\\
\textit{Italic イタリック体}\\
\textbf{\textit{Bold Italic 太字イタリック体}}\\
\textsf{Sans-serif サンセリフ体}\\
\textbf{\textsf{Bold Sans-serif 太字サンセリフ体}}\\
\end{document}
今回はフォントを指定して、簡単な文書を表示するものにします。
このletaxで使われるフォントとグラフのフォントを合わせるのが今回の目標です。
数式フォント以外はシステムにインストールされたものでも、プロジェクトのディレクトリに置いてパスで指定したものでも構いません。ディレクトリに置いてパスで指定する時は絶対パスを使うようにしてください。数式フォントはシステムにインストールしておきましょう。
そうしないとエラーでできなかった
簡単なtexファイルを用意したところでグラフを生成していきます。
まずはmatplotlibの設定ファイルmatplotlibrcを作ります。
axes.unicode_minus: True
text.usetex: True
pgf.rcfonts: False
pgf.preamble: \usepackage{fontspec}\usepackage{unicode-math}\usepackage{luatexja-fontspec}\setmainfont[Path=/absolute/path/to/fontdir/,UprightFont=STIXTwoText-Regular.ttf,ItalicFont=STIXTwoText-Italic.ttf,BoldFont=STIXTwoText-Bold.ttf,BoldItalicFont=STIXTwoText-BoldItalic.ttf]{STIX Two Text}\setsansfont[Path = /absolute/path/to/fontdir/,UprightFont=NotoSans-Regular.ttf,ItalicFont=NotoSans-Italic.ttf,BoldFont=NotoSans-Bold.ttf,BoldItalicFont=NotoSans-BoldItalic.ttf]{Noto Sans}\setmathfont{STIX Two Math Regular}\setmainjfont[Path=/absolute/path/to/fontdir/,UprightFont=NotoSerifJP-Regular.ttf,BoldFont=NotoSerifJP-Bold.ttf]{Noto Serif JP}\setsansjfont[Path = /absolute/path/to/fontdir/,UprightFont=NotoSansJP-Regular.ttf,BoldFont=NotoSansJP-Bold.ttf]{Noto Sans JP}
pgf.texsystem: lualatex
pgf.preambleはtexファイルのプリアンブルと同じものを指定してください。ただし改行を消して1行にまとめてください。
補足
実際にはtexファイルでフォントを指定する時、相対パスにしても動きます。
texファイル内でフォントを相対パスで指定したときもmatplotlibrcでは絶対パスで指定してください。そうしないとmatplotlibがフォントを見つけられずエラーを吐きます。
次にグラフを生成していきましょう。
さっきのグラフを生成するプログラムとほとんど同じなので、変更点だけ載せます。
- save_path = "sample.png"
- fig.savefig(save_path, dpi=300, bbox_inches="tight")
- plt.show()
+ save_path = "sample.pgf"
+ fig.savefig(save_path, bbox_inches="tight", pad_inches=0, transparent=True)
+ plt.close(fig)
これでpythonを実行してみましょう。sample.pgfというファイルができるはずです。
そうしたらこれをtexに読み込みます。
プリアンブルに追加してください。
\usepackage{float}
\usepackage{tikz}
\def\mathdefault#1{#1}
グラフを読み込みたいところに挿入してください。
\begin{figure}[H]
\centering
\input{sample.pgf}
\end{figure}
これでtexをコンパイルするとグラフが挿入された、PDFができるはずです。
終わりに
これをやり始めると意味わかんないエラーで時間が消えます。レポートのためにやり始めると寝られなくなるので注意。
ただ出来上がるレポートは綺麗になるので気になるよって人はやってみてください。
終わりに2
matplotlibrcに追加をすると色々できます
おすすめ
xtick.top: True
xtick.bottom: True
xtick.direction: in
ytick.left: True
ytick.right: True
ytick.direction: in
excelよりもできること多いのでぜひpythonでグラフ作ってみてください。