座標軸の数値の増加を任意の関数にする
概要
第一稿.
何らかの関数をグラフにする場合、一般的な \(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\)
のようにすればよい。
例: 無限大を見る
関数のグラフは無限に広がっているため,どうやっても一部分しか描けないと思われるかもしれませんが,全体を表示する方法もあります. pic.twitter.com/ptuOR933PK
— きいねく (@Keyneqq) March 4, 2021
これが面白そうだと思ったので描いてみた。
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)" #, \
さらに両対数を間に挟んだが、あまり使い道が思い浮かばない。
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))}" # , \