UP | HOME

座標軸の数値の増加を任意の関数にする

概要

[2021-03-08 Mon] 作成.
[2021-03-08 Mon]–[2021-03-12 Fri] 第一稿.

何らかの関数をグラフにする場合、一般的な \(x – y\) の軸であると都合が悪い場合がある。高校以降に登場する対数グラフはその解決策の一つであるが、他の関数におけるグラフはどうなるのだろうか。

通常のグラフ

軸の数字は \(x=[0, 1, 2, 3, 4, \dots], y=[0, 1, 2, 3, 4, \dots]\) という風に増加する。これを敢えて関数で表現すると \(x=x, y=y\) となるが、これではどちらが軸か分からなくなる。ここで、軸の値の増加の仕方を表現するために添字 axis を付けて、

$$ \begin{aligned} x _{\mathrm{axis}} &= x, \\ y _{\mathrm{axis}} &= y \end{aligned} $$

とする。この時点ではグラフ上の関数が従うのは \(x _{\mathrm{axis}}, y _{\mathrm{axis}}\) であって \(x, y\) ではない。

とはいえ、今回はまだ軸の関数とグラフ上の関数が従う値が同じなので、分かりにくいかもしれない。

片対数グラフ

軸の数字は \(x _{\mathrm{axis}}=[0, 1, 2, 3, 4, \dots], y _{\mathrm{axis}}=[1, 10, 100, 1000, 10000, \dots]\) という風に増加する。これを先程のように添字で表現すると、

$$ \begin{aligned} x _{\mathrm{axis}} &= x, \\ y _{\mathrm{axis}} &= 10 ^{y} \end{aligned} $$

とできる。

たとえばこのグラフ上に関数 \(y = x ^2+1\) を描画したいとする。
もちろん \((x, y)\) の各点をとっていき、その点を繋ぐような曲線を書くという方法もある。しかしこれはグラフ用ソフトなどを用いる時に都合が悪い。
よって \(x, y\) だけを通常の軸に戻す方法を考えた。

まず、 \(x=[0, 1, 2, 3, 4, \dots], y=[0, 1, 2, 3, 4, \dots]\) が基準であること、描画したいのは \(y _{\mathrm{axis}} = x _{\mathrm{axis}} ^2+1\) であることを確認する。これを \(x, y\) について解くと、 \(y = \log _{10}(x ^2+1)\) である。
そしてこの関数を \(x, y\) 上に描く。最後に軸を \(y\) から \(y _{\mathrm{axis}}\) にする。つまり

  • \(y=1\) の位置に値 \(y _{\mathrm{axis}}=10\) と書く
  • \(y=2\) の位置に値 \(y _{\mathrm{axis}}=100\) と書く
  • \(y=3\) の位置に値 \(y _{\mathrm{axis}}=1000\) と書く

両対数グラフ

要領は片対数と同じである。

$$ \begin{aligned} x _{\mathrm{axis}} &= 10 ^{x}, \\ y _{\mathrm{axis}} &= 10 ^{y} \end{aligned} $$

である。

\(x=[0, 1, 2, 3, 4, \dots], y=[0, 1, 2, 3, 4, \dots]\) が基準であること、描画したいのは \(y _{\mathrm{axis}} = x _{\mathrm{axis}} ^2+1\) であることを確認する。

これを \(x, y\) について解くと、 \(y = \log _{10}(10 ^{2x} +1)\) である。
そしてこの関数を \(x, y\) 上に描く。最後に軸を \(x\) から \(x _{\mathrm{axis}}\) に、 \(y\) から \(y _{\mathrm{axis}}\) にする。

一般の関数の場合

$$ \begin{aligned} x _{\mathrm{axis}} &= g(x), \\ y _{\mathrm{axis}} &= h(y) \end{aligned} $$

の時も同様である。

\(x=[0, 1, 2, 3, 4, \dots], y=[0, 1, 2, 3, 4, \dots]\) が基準であること、描画したいのは \(y _{\mathrm{axis}} = f(x)\) であることを確認する。

これを \(x, y\) について解くと、 \(y = h ^{-1}(f(g(x))))\) である。
そしてこの関数を \(x, y\) 上に描く。最後に軸を \(x\) から \(x _{\mathrm{axis}}\) に、 \(y\) から \(y _{\mathrm{axis}}\) にする。

ただし、軸の関数 \(g, h\) は、変数と結果が一対一対応するものであることが重要である。上の例で用いた指数関数は一対一対応する。
一対一対応しない関数を軸に用いると、軸上で同じ位置に異なる値を持つことになってしまうからである。

これで様々な関数を軸にとれるようになるのだが、何を等間隔にするのかを意識するべきである。
たとえばアレニウスプロットをする場合、 \(1/x\) を\(x\)軸にするのだが、 \(x _{\mathrm{axis}} = 1/x\) としてしまうと、\([1, 1/2, 1/3, 1/4, \dots]\) が均等な幅になってしまう。なので関数やデータを変換(gnuplot なら plot data using (1.0/$1):2 など)して描画するのが良いだろう。

gnuplot での描画

一般の関数の場合で考えた関数を gnuplot で描画すると以下のようになる。ただし、関数 \(h ^{-1}\) は自分で計算して導出する必要がある。

set xrange [0:10]
set yrange [0:10]

set xtics ()
set for [i=0:10] xtics add (sprintf('%.2g', g(i)) i)

set ytics ()
set for [i=0:10] ytics add (sprintf('%.2g', h(i)) i)

plot h^{-1}(f(g(x)))

もちろん軸上の数字も任意の位置にできる。

set xrange [0:10]
set yrange [0:10]

set xtics (
    sprintf('%.2f', g(1)) 1, \
    sprintf('%.2f', g(5)) 5, \
    sprintf('%.2f', g(10)) 10 \
                    )

set ytics (
    sprintf('%.2f', h(1)) 1, \
    sprintf('%.2f', h(4)) 3, \
    sprintf('%.2f', h(8)) 8 \
                    )

plot h^{-1}(f(g(x)))

新しい軸上で \([1, 2, 3, 4, \dots]\) を描画する

一般の関数の場合で考えると、

  • \(x=1\) の位置にラベル \(x _{\mathrm{axis}} = g(1)\)
  • \(x=2\) の位置にラベル \(x _{\mathrm{axis}} = g(2)\)
  • \(x=3\) の位置にラベル \(x _{\mathrm{axis}} = g(3)\)

のように軸をとった。よって、

  • \(x=g ^{-1}(1)\) の位置にラベル \(x _{\mathrm{axis}} = 1\)
  • \(x=g ^{-1}(2)\) の位置にラベル \(x _{\mathrm{axis}} = 2\)
  • \(x=g ^{-1}(3)\) の位置にラベル \(x _{\mathrm{axis}} = 3\)

のようにすればよい。

例: 無限大を見る

これが面白そうだと思ったので描いてみた。

reset
set encoding utf8
set terminal svg enhanced size 600,400 font "Arial:Bold,12" # svg
set size ratio 1 # 1:(x/y), -1 for 1:1 axes

set lmargin 0 # unset
set rmargin 8
set tmargin 2
set bmargin 2

set grid linetype 1 linewidth 0.75 linecolor "gray"

set title   font ",14" offset 0,-1      rotate by 0 center
set xlabel  font ",14" offset 0,1.0     rotate by 0 center # 3D: parallel
set ylabel  font ",14" offset 2.0,1.0   rotate by 90 center # 3D: parallel

set xtics   font ",12" offset -0.0,0.5  rotate by 0   mirror
set ytics   font ",12" offset 0.1,0     rotate by 0   mirror

f1(x) = 10**x
f2(x) = (x-1)*(x-2)*(x-3)
f3(x) = -x+7
f4(x) = x+sin(2*pi*x)
f5(x) = -2+sqrt(4-(x+1)**2)
f6(x) = -2-sqrt(4-(x+1)**2)

g(x) = x / (1.0 - abs(x))
g_inv(x) = x / (1.0 + abs(x))

h(x) = x / (1.0 - abs(x))
h_inv(x) = x / (1.0 + abs(x))

set samples 1000                             # default: 100

set title "F(x) = x / (1 - |x|) :  F( f( F^{-1}(x) ) )"
# key: http://dsl4.eee.u-ryukyu.ac.jp/DOCS/gnuplot/node96.html
set key right outside \
    box linestyle -1 linewidth 0.75 linecolor rgb "gray" \
    width -5 spacing 1.1 \
    title "f(x):" font ",12" # 凡例

# --- X AXIS ---
set xlabel "{/:Italic x}"
set xrange [-1:1] noreverse
set xtics ()
set xtics add ("-∞" -1, "∞" 1)
set xtics add ("-7" -7.0/8, "7" 7.0/8)
set xtics add ("-1/3" -1.0/4, "1/3" 1.0/4)
set for [i=-3:3] xtics add (sprintf("%d", i) g_inv(1.0*i))

# --- Y AXIS ---
set ylabel "{/:Italic y}"
set yrange [-1:1] noreverse
set ytics ()
set ytics add ("-∞" -1, "∞" 1)
set ytics add ("-7" -7.0/8, "7" 7.0/8)
set ytics add ("-1/3" -1.0/4, "1/3" 1.0/4)
set for [i=-3:3] ytics add (sprintf("%d", i) g_inv(1.0*i))
# set for [i=-10:4:2] ytics add (sprintf("10^{%.2g}", i/100.0) i/100.0)

plot \
     h_inv(f1(g(x))) with lines lw 2 lt 1 title "10^{x}", \
     h_inv(f2(g(x))) with lines lw 2 lt 2 title "(x-1)(x-2)(x-3)" , \
     h_inv(f3(g(x))) with lines lw 2 lt 3 title "-x+7" , \
     h_inv(f4(g(x))) with lines lw 2 lt 4 title "x+sin(2πx)" , \
     h_inv(f5(g(x))) with lines lw 2 lt 6 title "-2+sqrt((x+1)^2-2^2)" , \
     h_inv(f6(g(x))) with lines lw 2 lt 6 title "-2-sqrt((x+1)^2-2^2)" #, \
Sorry, your browser does not support SVG.

さらに両対数を間に挟んだが、あまり使い道が思い浮かばない。

reset
set encoding utf8
set terminal svg enhanced size 400,600 font "Arial:Bold,12" # svg
set size ratio 1 # 1:(x/y), -1 for 1:1 axes

set lmargin 7 # unset
set rmargin 1
set tmargin 1
set bmargin 2

set grid linetype 1 linewidth 0.75 linecolor "gray"

set title   font ",14" offset 0,-1      rotate by 0 center
set xlabel  font ",14" offset 0,1.0     rotate by 0 center # 3D: parallel
set ylabel  font ",14" offset 2.0,1.0   rotate by 90 center # 3D: parallel

set xtics   font ",12" offset -0.0,0.5  rotate by 0   mirror
set ytics   font ",12" offset 0.1,0     rotate by 0   mirror

f1(x) = 10**x-1
f2(x) = exp((x-1)*(x-0.1)/(x-10)/(x-0.001)))

g(x) = x / (1.0 - abs(x))
g_inv(x) = x / (1.0 + abs(x))

h(x) = 10**x
h_inv(x) = log10(x)

set samples 4000                             # default: 100

set title "F( log10( f( 10**( F^{-1}(x) ) ) ) )"
set key below \
    box linestyle -1 linewidth 0.75 linecolor rgb "gray" \
    width -5 spacing 1.1 \
    title "f(x):" font ",12" # 凡例

# --- X AXIS ---
set xlabel "{/:Italic x}"
set xrange [-1:1] noreverse
set xtics ()
set xtics add ("0" -1, "∞" 1)
set xtics add ("10^{-7}" -7.0/8, "10^{7}" 7.0/8)
set xtics add ("10^{-1/3}" -1.0/4, "10^{1/3}" 1.0/4)
set for [i=-3:3] xtics add (sprintf("10^{%d}", i) g_inv(1.0*i))

# --- Y AXIS ---
set ylabel "{/:Italic y}"
set yrange [-1:1] noreverse
set ytics ()
set ytics add ("0" -1, "∞" 1)
set ytics add ("10^{-7}" -7.0/8, "10^{7}" 7.0/8)
set ytics add ("10^{-1/3}" -1.0/4, "10^{1/3}" 1.0/4)
set for [i=-3:3] ytics add (sprintf("10^{%d}", i) g_inv(1.0*i))

plot \
     g_inv(h_inv(f1(h(g(x))))) with lines lw 2 lt 1 title "10^{x} - 1" , \
     g_inv(h_inv(f2(h(g(x))))) with lines lw 2 lt 2 title "{/=8 exp((x-0.1)(x-1)/(x-0.001)(x-10))}" # , \
Sorry, your browser does not support SVG.

Created: 2021-03-17 Wed 17:05

Validate