グラフの上下左右軸に主目盛・副目盛をつける

20世紀の大昔,サイエンティフィックなグラフというものは上下左右軸に目盛をつけるものだと偉い先生に教えられたことがある。その理由は,定規を水平または垂直に当ててグラフの曲線から数値を読み取るためだと言われて,妙に感心したことを覚えている。というわけで,上下左右軸に目盛をつけた,サイエンティフィックなグラフを描く例。

SymPy + SymPy Plotting Backends (SPB) を追加。2023.3.18

gnuplot

gnuplot では標準で上下左右に(主)目盛がつく

$y = \sin x$ のグラフを $-5 \leq x \leq 5$ の範囲で描く例。

In [1]:
plot [-5:5] sin(x)

gnuplot で主目盛・副目盛の設定

In [2]:
# x 軸の主目盛を 1 ごとに; 副目盛は主目盛を5等分に
set xtics 1; set mxtics 5
# y 軸の主目盛を 0.5 ごとに; 副目盛は主目盛を5等分に
set ytics 0.5; set mytics 5

plot [-5:5] sin(x)

その他のオプションもつけて…

In [3]:
# 主目盛・副目盛の設定
set xtics 1; set mxtics 5
set ytics 0.5; set mytics 5

# x 軸 y 軸を描く
set zeroaxis

# グリッド(格子線)を描く
set grid

# x 軸のラベル
set xlabel "x"
# y 軸のラベル
set ylabel "sin(x)"

# y 軸の表示範囲の設定
set yrange [-1.1:1.1] 

# notitle で凡例非表示,線の太さ line width (lw) を 2 に
plot [-5:5] sin(x) notitle lw 2

Maxima の plot2d()

plot2d() では標準では上下左右に(主)目盛がつく

$y = \sin x$ のグラフを $-5 \leq x \leq 5$ の範囲で描く例。

In [1]:
plot2d(
  sin(x), [x, -5, 5]
)$

plot2d() で主目盛・副目盛の設定

plot2d() のオプション [xtics, ...][ytics, ...] で大目盛の設定は可能ですが, (弘大 JupyterHub の)Maxima は gnuplot を使ってグラフを描いているので,gnuplot のオプションを直接設定してやることで詳細な設定が可能。書式は以下のように。

In [2]:
plot2d(
  sin(x), [x, -5, 5], 

  /* x 軸の主目盛を 1 ごとに; 副目盛は主目盛を5等分に */
  /* y 軸の主目盛を 0.5 ごとに; 副目盛は主目盛を5等分に */
  [gnuplot_preamble, "set xtics 1; set mxtics 5;
                      set ytics 0.5; set mytics 5;"]
)$

grid2d のオプションもつけて…

In [3]:
plot2d(
  sin(x), [x, -5, 5], 

  /* グリッド(格子線)を描く */
  grid2d,

  /* x 軸の主目盛を 1 ごとに; 副目盛は主目盛を5等分に */
  /* y 軸の主目盛を 0.5 ごとに; 副目盛は主目盛を5等分に */
  [gnuplot_preamble, "set xtics 1; set mxtics 5;
                      set ytics 0.5; set mytics 5;"]
)$

Maxima の draw2d()

draw2d() の標準では下と左にしか目盛がつかない

陽関数 $y = \sin x$ のグラフを $-5 \leq x \leq 5$ の範囲で描く場合は explicit(sin(x), ...) のように。

In [4]:
draw2d(
  explicit(sin(x), x, -5, 5)
)$

draw2d() で上下左右に目盛をつける

(弘大 JupyterHub の)Maxima は gnuplot を使ってグラフを描いているので,gnuplot のオプションを設定してやる。書式は以下のように user_preamble = "set ...;"

In [5]:
draw2d(
  /* 上下左右に目盛をつける */
  user_preamble = "set xtics mirror; set ytics mirror;",

  explicit(sin(x), x, -5, 5)
)$

draw2d() で主目盛・目盛小目盛の設定

In [6]:
draw2d(
  /* 上下左右に目盛をつける */
  /* x 軸の主目盛を 1 ごとに; 副目盛は主目盛を5等分に */
  /* y 軸の主目盛を 0.5 ごとに; 副目盛は主目盛を5等分に */
  user_preamble = "set xtics mirror; set ytics mirror;
                   set xtics 1; set mxtics 5; 
                   set ytics 0.5; set mytics 5;",

  explicit(sin(x), x, -5, 5)
)$

その他のオプションもつけて…

In [7]:
draw2d(
  /* 上下左右に目盛をつける */
  /* x 軸の主目盛を 1 ごとに; 副目盛は主目盛を5等分に */
  /* y 軸の主目盛を 0.5 ごとに; 副目盛は主目盛を5等分に */
  /* グリッド(格子線)を描く */
  user_preamble = "set xtics mirror; set ytics mirror;
                   set xtics 1; set mxtics 5; 
                   set ytics 0.5; set mytics 5;
                   set grid;",

  /* グリッド(格子線)は grid = true, でもできるが結果が異なる 
  grid = true, */

  /* y 軸の表示範囲の設定 */
  yrange = [-1.1, 1.1], 

  /* x 軸 y 軸を描く */
  xaxis =true, yaxis =true, 

  /* x 軸のラベル,y 軸のラベル */
  xlabel = "x", ylabel = "sin(x)", 

  /* 線の太さ line_width を 2 に */
  line_width = 2, 
  explicit(sin(x), x, -5, 5)
)$

user_preamble = "..." で副目盛を指定した場合,user_preamble = "set grid;" でグリッドを指定した場合と,user_preamble ではなく,grid = true, で指定した場合では結果が異なる。

以下のように,grid = true, で指定した場合は,主・副目盛全てにグリッドを描いてしまう。

In [8]:
draw2d(
  /* 上下左右に目盛をつける */
  /* x 軸の主目盛を 1 ごとに; 副目盛は主目盛を5等分に */
  /* y 軸の主目盛を 0.5 ごとに; 副目盛は主目盛を5等分に */
  user_preamble = "set xtics mirror; set ytics mirror;
                   set xtics 1; set mxtics 5; 
                   set ytics 0.5; set mytics 5;
                   ",
  /* グリッド(格子線)は grid = true, でもできるが結果が異なる */
  grid = true, 
  /* 主・副目盛全てにグリッドを描いてしまう */

  /* y 軸の表示範囲の設定 */
  yrange = [-1.1, 1.1], 
  /* x 軸 y 軸を描く */
  xaxis =true, yaxis =true, 
  /* x 軸のラベル,y 軸のラベル */
  xlabel = "x", ylabel = "sin(x)", 

  /* 線の太さ line_width を 2 に */
  line_width = 2, 
  explicit(sin(x), x, -5, 5)
)$

matplotlib.pyplot.plot()

In [1]:
# NumPy も使います
import numpy as np
# Matplotlib でグラフを描きます
import matplotlib.pyplot as plt

# 以下はグラフを SVG で Notebook にインライン表示させる設定
%config InlineBackend.figure_formats = ['svg']

plt.plot() は標準では下と左にしか目盛がつかない

$y = \sin x$ のグラフを $-5 \leq x \leq 5$ の範囲で描く例。

まず,$x$ 軸用に $-5 \leq x \leq 5$ を(ここでは)200 等分したリスト x を作り,$y$ 軸用には y = np.sin(x) としたリスト y を作り, plt.plot(x, y) でグラフを描く。

In [2]:
x = np.linspace(-5, 5, 201)
y = np.sin(x)

plt.plot(x, y);

plt.plot() で上下左右に(内向きに)目盛をつける

In [3]:
#グラフの上下左右に目盛を付ける。
f = plt.figure()
ax = f.add_subplot(111)
ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')

# tick の向きを内側に
plt.tick_params(which ="both",direction = 'in')

plt.plot(x, y);

plt.plot() で主目盛・副目盛の設定

In [4]:
#グラフの上下左右に目盛を付ける。
f = plt.figure()
ax = f.add_subplot(111)
ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')

# tick の向きを内側に
plt.tick_params(which ="both",direction = 'in')

# x の主目盛を 1 刻みに
plt.xticks(np.arange(-5, 6, 1))
# y の主目盛を 0.5 刻みに
plt.yticks(np.arange(-1., 1.1, 0.5))
# 副目盛も表示(副目盛の個数とかのオプション設定は?)
plt.minorticks_on()

plt.plot(x, y);

その他のオプションもつけて…

In [5]:
#グラフの上下左右に目盛を付ける。
f = plt.figure()
ax = f.add_subplot(111)
ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')

# tick の向きを内側に
plt.tick_params(which ="both",direction = 'in')

# x の主目盛を 1 刻みに
plt.xticks(np.arange(-5, 6, 1))
# y の主目盛を 0.5 刻みに
plt.yticks(np.arange(-1., 1.1, 0.5))
# 副目盛も表示(副目盛の個数とかのオプション設定は?)
plt.minorticks_on()

# 主目盛にグリッド(格子線)
plt.grid(which="major", color="lightgray", ls="--", linewidth=0.5)

# x軸 y軸
plt.axhline(0, color='black', dashes=(5, 5), linewidth=0.5)
plt.axvline(0, color='black', dashes=(5, 5), linewidth=0.5)

# x 軸の表示範囲
plt.xlim([-5,5])
# y 軸の表示範囲
plt.ylim([-1.1, 1.1])

# x 軸のラベル
plt.xlabel("x")
# y 軸のラベル
plt.ylabel("sin(x)")

# 線の太さ linewidth を 2.5 に
plt.plot(x, y, linewidth = 2.5);

SymPy の plot() は標準では外枠がつかない

In [1]:
from sympy import *
# 1文字変数の Symbol の定義が省略できる
from sympy.abc import *

# グラフを SVG で Notebook にインライン表示
%config InlineBackend.figure_formats = ['svg']
In [2]:
plot(sin(x), (x, -5, 5));

SPB の plot() は標準では下と左に目盛がつく

SPB を import すると外枠とグリッドも標準でつく。それはそれでありがたいのだが,gnuplot や Maxima で慣れた目では,実線のグリッドが少し目障りに見える。また,Python の Matplotlib 界隈では $x$ 軸($y=0$)や $y$ 軸($x=0$)を(グリッドとは別に)引く慣習がないのか,オプションが見当たらない。

In [3]:
from spb import *

plot(sin(x), (x, -5, 5));

SPB plot() で上下左右に(内向きに)目盛をつける

一旦 SymPy Plotting Backends で p = plot() などとしてプロットしたら,あとは ax = p.ax として ax に対して通常どおりの Matplotlib のオプション設定をしていけばよい。

In [4]:
p = plot(sin(x), (x, -5, 5), show = False)

ax = p.ax

# 一旦 ax にしたら後は Matplotlib と同様に
# グラフの上下左右に目盛を付ける
ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')

# tick の向きを内側に
ax.tick_params(which ="both",direction = 'in');

SPB plot() で主目盛・副目盛の設定

np.linspace()np.arange() を使わず,NumPy に頼らずに ticks の設定をしてみる。また,グリッドを灰色の細め点線にして,gnuplot や Maxima にように(あまり目立たないように)してみる。

In [5]:
# 表示範囲の設定
p = plot(sin(x), (x, -5, 5), 
         xlim = (-5, 5), ylim = (-1.1, 1.1), show = False)

ax = p.ax
ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')
ax.tick_params(which ="both",direction = 'in')

# x の主目盛を 1 刻みに
ax.set_xticks([i for i in range(-5,6)])
# y の主目盛を 0.5 刻みに
ax.set_yticks([0.5*i for i in range(-2,3)])

# 副目盛も表示
ax.minorticks_on()
# 副目盛には grid をつけない
ax.grid(False, which="minor")
# x の副目盛を 0.2 刻みに
ax.set_xticks([0.2*i for i in range(-25,26)], minor = True)
# y の副目盛を 0.1 刻みに
ax.set_yticks([0.1*i for i in range(-10,11)], minor = True)

# 主目盛の grid を細い点線で
ax.grid(True, which="major", color="lightgray", 
        dashes=(3, 5), linewidth=0.5);

その他のオプションもつけて…

$x$ 軸($y=0$)と $y$ 軸($x=0$)を引く。特に専用のオプションが用意されているわけではないようなので,axhline(0)axvline(0) で黒色の細め点線で描いてみる。

In [6]:
# 軸のラベル
p = plot(sin(x), (x, -5, 5), 
         xlim = (-5, 5), ylim = (-1.1, 1.1), 
         xlabel = "$x$", ylabel = "$\sin x$", 
         show = False)

ax = p.ax
ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')
ax.tick_params(which ="both",direction = 'in')
ax.set_xticks([i for i in range(-5,6)])
ax.set_yticks([0.5*i for i in range(-2,3)])
ax.minorticks_on()
ax.grid(False, which="minor")
ax.set_xticks([0.2*i for i in range(-25,26)], minor = True)
ax.set_yticks([0.1*i for i in range(-10,11)], minor = True)
ax.grid(True, which="major", color="lightgray", 
        dashes=(3, 5), linewidth=0.5)

# x軸 y軸
ax.axhline(0, color='black', dashes=(3, 5), linewidth=0.5)
ax.axvline(0, color='black', dashes=(3, 5), linewidth=0.5);

横軸の目盛を π/2 ごとに

別ページにもまとめているが,横軸の主目盛 xticks を $\pi/2$ ごとに,副目盛を $\pi/10$ ごとに打つ例。既約分数表記にするところが工夫した点。

In [7]:
# π
from sympy import pi
Pi = float(pi)

p = plot(sin(x), (x, -2*Pi, 2*Pi), 
         xlim = (-2*Pi, 2*Pi), ylim = (-1.1, 1.1), 
         xlabel = "$x$", ylabel = "$\sin x$", 
         show = False)
ax = p.ax

# x 軸の主目盛は 0.5π ごとに
ax.set_xticks(
    [(0.5*i*Pi) for i in range(-4, 5)])
# x 軸の主目盛のラベル。既約分数表記で。
ax.set_xticklabels(
    [(str(Rational(i,2))+" $\pi$") for i in range(-4, 5)])
# 手動で設定する場合
# ax.set_xticklabels(
#    ["$-2 \pi$", " $-3 \pi/2$", "-$\pi$", "-$\pi/2$", "0",
#     "$\pi/2$", "$\pi$", "$3\pi/2$", "$2\pi$"])

ax.set_yticks([(0.5*i) for i in range(-2,3)])

ax.xaxis.set_ticks_position('both')
ax.yaxis.set_ticks_position('both')
ax.tick_params(which ="both",direction = 'in')

ax.minorticks_on()
ax.grid(False, which="minor")

# x の副目盛を 0.1π ごとに
ax.set_xticks([
    (0.1*Pi*i) for i in range(-20,21)], minor = True)

ax.set_yticks([(0.1*i) for i in range(-10,11)], minor = True)
ax.grid(True, which="major", color="lightgray", 
        dashes=(3, 5), linewidth=0.5)

# x軸 y軸
ax.axhline(0, color='black', dashes=(3, 5), linewidth=0.5)
ax.axvline(0, color='black', dashes=(3, 5), linewidth=0.5);