第4回:▼ 不連続な曲線を描く

■ データ系列の見かけの調整

■ 線の色の指定

線の色は linecolor=色 の形式で指定する. 別名 lc=色

色の名前で指定する

名前で指定できる色は,こちらのURLに列挙されている. → Named Colors

  • :red
  • :green
  • :blue
  • :cyan
  • :magenta
  • :yellow
  • :black
  • :white : (白背景では見えない)
aux = (label="", lc=:black, lw=0.5)

using Plots
#gr() #pythonplot()

Plots.reset_defaults()
default(
    thickness_scaling=2, framestyle=:box,
    legend_foreground_color=nothing,
    legend_background_color=nothing,
    linewidth=2)

plot(legend=:bottomright)
xs = -2:0.2:2
ys = xs .^ 3 - xs .^ 2 .+ 20
plot!(xs, ys,       lc=:red,     label="red")
plot!(xs, ys .- 2,  lc=:green,   label="green")
plot!(xs, ys .- 4,  lc=:blue,    label="blue")
plot!(xs, ys .- 6,  lc=:cyan,    label="cyan")
plot!(xs, ys .- 8,  lc=:magenta, label="magenta")
plot!(xs, ys .- 10, lc=:yellow,  label="yellow")
plot!(xs, ys .- 10, lc=:white,   label="white")
plot!(xs, ys .- 10, lc=:black,   label="black")

カラーパレットの番号で指定する

既定のカラーパレットでは,10色が自動的に選ばれる. 以下の例では,11本目から最初の色に戻っているが確認できる.

palette(:default)
using Plots
#gr() #pythonplot()

plot()
xs = -2:0.2:2
ys = xs .^ 3 - xs .^ 2 .+ 20
for i in 1:12
    plot!(ys .- 2i, lc=i, label=string(i))
end
plot!()

色系列(パレット)を指定することもできる.

Colorschemes

以下は,:tab10 を選んだ場合である.

palette(:tab10)
Note

Set1_9 は,Color Brewer2で提案されたカラーパレットの一つである.

palette(:Set1_9)
using Plots

plot(palette=:Set1_9)
xs = -2:0.2:2
ys = xs .^ 3 - xs .^ 2
for i in 1:12
    plot!(ys .- 2i, lc=i, label=string(i))
end
plot!()
Note

tab10 は,tableauで用いられるカラーパレットに基づいている.Color Palettes and Effects

  • qualitative または categorical : 区別する
  • diverging : 負の値から0を取り,再び増える数字
  • sequential : 0から増えていく数字

■ 線の形状

using Plots
#gr() #pythonplot()

plot(palette=:Set1_9)
xs = -2:0.2:2
ys = xs .^ 3 - xs .^ 2 .+ 20
i = 1
for s in [
    :solid, :dot, :dash, :dashdot ]
    plot!(ys .- 2i, linestyle=s, lc=2, label=string(s))
    global i += 1
end
plot!()

■ マーカーの設定

  • markersize=数字

※ 別名 ms=数字

  • markercolor=色

※ 別名 mc=色

  • markershape=形

※ 別名 shape=色

using Plots
#gr() #pythonplot()

plot(palette=:Set1_9)
# 円・赤塗りつぶし・枠線なし
plot([0],[0], seriestype=:scatter,
    markershape=:circle, markersize=18,
    mc=:red,
    markerstrokewidth=0)
# 円・赤枠のみ・内側は白
plot!([1],[1], seriestype=:scatter,
    markershape=:circle, markersize=18,
    mc=:white,
    markerstrokecolor=:red,
    markerstrokewidth=3)
plot!(xlims=(-0.5,2),ylims=(-0.5,2))

alpha値は,不透明度であり 0 から 1までの値を取る. 0は不透明,1は透明である.

  • markershape :
  • markersize
  • markeralpha
  • markercolor

※ markerstrokeは,マーカーの外側の枠線を指定する

  • markerstrokewidth
  • markerstrokealpha
  • markerstrokecolor
  • markerstrokestyle
using Plots
#gr() #pythonplot()

plot(palette=:Set1_9)
i = 1
for t in [
    :circle, :rect, :diamond, :cross, :xcross ]
    plot!([i], [1], seriestype=:scatter,
        markershape = t,
        lc=2, label=string(t))
    global i += 1
end
xlims!(0,i)
ylims!(0,i)
plot!()

■ 散布図の作成

using Plots
#gr() #pythonplot()

plot(palette=:Set1_9)
xs = -2:0.2:2
ys = xs .^ 3 - xs .^ 2 .+ 20
i = 1
for t in [ :path, :scatter ]
    plot!(ys .- 2i, seriestype=t, lc=2, label=string(t))
    global i += 1
end
plot!()

■ プロットデフォルトの設定4

using Plots
#gr() #pythonplot()

Plots.reset_defaults()
default(
    framestyle=:box,thickness_scaling=2,
    aspect_ratio=:auto,
    label="",
    legend_foreground_color=nothing,
    legend_background_color=nothing,
    grid=false,xlabel="", ylabel="",
    palette=:Set1_9,
    linewidth=2,
    markershape=:none,
    markersize=2,
    markerstrokewidth=0)

■ 0による除算

筆算では 0 による除算の結果は未定義である.

Julia では,0 による除算は,例外は発生せず, 「数でない数」 Inf, -Inf, NaN のどれかが得られる.

Inf は,無限大 Infinity に由来する. NaN は,数でない Not a Number に由来する.

julia> 1 / 0Inf
julia> -1 / 0-Inf
julia> 0 / 0NaN

▼ 関数が連続とは

関数が連続であるとは, 関数のプロットがつながっている,ちぎれていないことをいう.

「関数 $f(x)$$x=a$ で連続」とは,

\[\lim_{x \longrightarrow a} f(x)\]

が存在して,その値が $f(a)$ に等しいと定義される.

不連続とは,連続でないことである. ただし,不連続な関数の多くは,連続な部分(枝,branch)を含む,

この章では,主に,連続ではない関数のプロットを描く.

▼ 逆数関数を描く

逆数関数 $y=\dfrac{1}{x}$ を描いてみよう.

Note

逆数関数 reciprocal function という.逆関数 inverse function と区別されたい.

さて,$\dfrac{1}{0}$ の値は Inf であるが,plot 関数は「数でない数」をスキップして何も描かない.分母 $0$ の除算を特別扱いする必要はない.

逆数関数は,$x=0$ で不連続であり,$x$ の正負に対応して2つの枝を持つ.

plot(aspect_ratio=:equal, legend=:topleft)

xs = -3:0.1:3
plot!(xs, 1.0 ./ xs, label="y=1/x")
xlims!(-3, 3)
ylims!(-3, 3)

続けて,$y=x$$y=-x$,水平線 $y = 0$,垂直線 $x = 0$,を追加しよう.

# 続けて
plot!(xs, -1*xs; aux...)
plot!(xs, xs; aux...)
hline!([0]; aux...)
vline!([0]; aux...)

▲ 練習

(プログラミングでなく,数学の話題)

数学では「何らかの操作を行った結果が,元と重なること」を, その操作に対して対称である(symmetric)という.

上のプロットを観察すると,逆数関数は,いくつかの操作に対して対称であることがわかる.どのような操作か?

▼ 不連続な有理式を描く

有理関数とは,多項式(分子)を多項式(分母)で割った関数である.

以下の有理関数を描こう.

\[y = \dfrac{x^3+8}{x^3+3x^2-4x-12}\]

まず,分母を描く.

aux = (label="", lc=:black, lw=0.5)
plot(legend=:top)

xs = -10:0.1:10
qs = xs .^ 3 .+ 3xs .^ 2 .- 4xs .- 12
plot!(xs, qs, label="denominator")
ylims!(-20, 20)
xlims!(-4, 4)
vline!([-3,-2,2]; aux...)
hline!([0]; aux...)

分母は $x=-3, -2, 2$$0$ となるから, 上の有理関数は,この三点で不連続となる「可能性」がある.

では,上の有理関数を描いてみる. 逆数関数の描画と同じように,分母 $0$ となる場合を特別扱いする必要はない.

plot(legend=:top)
xs = -10:0.1:10
ps = xs .^ 3 .+ 8
qs = xs .^ 3 .+ 3xs .^ 2 .- 4xs .- 12
ys = ps ./ qs
plot!(xs, qs, label="rational function")
ylims!(-10, 10)
xlims!(-4, 4)
hline!([0]; aux...)
vline!([-3,-2,2]; aux...)

実際には,$x=-2$ では不連続ではない. 分子・分母を共通項 $(x+2)$ で割れるからである.

もう少し,横軸の範囲を狭めて描く.

# 続けて
ylims!(-10, 10)
xlims!(-3, 3)

▲ 練習

上の有理関数で,$x=-2$ に対する値を求めよ.

分子・分母は共通項 $(x+2)$ で割った関数のプロットを描き, 上のプロットと重なることを確かめよ.2つの曲線を比較するための描き方は,下の ▼ 周期関数 を参考にせよ(本章を通読してから取り組め).

▼ 正接関数・余接関数を描く

  • 正接 $y = \tan{x} =\dfrac{\sin{x}}{\cos{x}}$
  • 余接 $y = \cot{x} =\dfrac{\cos{x}}{\sin{x}}$
関数数式ラジアン単位角度単位
正接$\tan{x}$tan(x)tand(x)
余接$\cot{x}$cot(x)tand(x)

ラジアン単位

正接 $\tan{x}$は,$\dfrac{\pi}{2}$ の奇数倍で不連続である.

余接 $\cot{x}$は,$\dfrac{\pi}{2}$ の偶数倍で不連続である.

plot(xlabel="radian", ylims=(-10,10), size=(720,480))

xs = -2pi:pi/360:2pi
scatter!(xs, tan.(xs), label = "tan")
scatter!(xs, cot.(xs), label = "cot")
vline!(-2pi:pi/2:2pi; aux...)
plot!()

角度単位

using Plots
#gr() #pythonplot()
aux = (label="", lc=:black, lw=0.5)

plot(xlabel="degree", ylims=(-10,10),size=(720,480))
xs = -360:1:360
scatter!(xs, tand.(xs), label = "tand")
scatter!(xs, cotd.(xs), label = "cotd")
plot!(xticks=-360:90:360) # <= 横軸目盛の設定
vline!(-360:90:360; aux...)

▼ 周期関数

\[f(t+T) = f(t)\]

上式のように,横軸を $T$ だけ平行移動しても, 元の形に重なる関数を周期関数(periodic function)という. $T$ は,周期(period) と呼ばれる.

●▼ 周期関数を確認する

ラジアン単位の正接関数 tan は,周期 $2\pi$ である. 平行移動して重なることを,図示してみよう.

比較の基準となる曲線は,青い円(塗りつぶし)で描いた.

比較される曲線は,少し小さい赤い円(塗りつぶし)で描いた.

青い円の真ん中に,赤い点が描かれている.

using Plots
#gr() #pythonplot()
aux = (label="", lc=:black, lw=0.5)

xs = -2pi:pi/30:2pi
plot(grid=false, palette=:Set1_9,
    xlabel="radian", ylims=(-10,10),
    xlims=(-1.2pi,1.2pi),size=(720,480))
scatter!(xs, tan.(xs), lc=1, ms=4,
    label = "tan")
scatter!(xs, tan.(xs .+ 2 * pi), ms=2, lc=2,
    label = "tan, shifted by 2pi")
plot!(xticks=(-2pi:pi/2:2pi,[])) # <= 横軸目盛の設定
vline!(-2pi:pi/2:2pi; aux...)

▼ 符号関数を描く

Base.sign - Function

関数 sign(x) は,

  • 条件 $x > 0$ なら $1$ を,
  • 条件 $x = 0$ なら $0$ を,
  • 条件 $x < 0$ なら $-1$ を,

それぞれ返す.

using Plots
#gr() #pythonplot()
aux = (label="", lc=:black, lw=0.5)
plot()

xs = -5.0:0.1:5.0
plot!(xs, sign.(xs), label = "sign")
vline!([0]; aux...)

三角関数と関数 sign とを組み合わると, 不連続な周期関数を作ることができる.

▶ 方形波を描く

2つの一定値を交互にとる周期関数を方形波(square wave)という.

using Plots
#gr() #pythonplot()

aux = (label="", lc=:black, lw=0.5)
plot()

xs = -5.0:0.1:5.0
plot!(xs, cos.(xs), label = "cos()")
plot!(xs, sign.(cos.(xs)), label = "sign(cos())")
vline!([0]; aux...)

▲ 練習

  • 上の例の周期はいくつか?
  • 周期が 1 になるように,変更してみよ.プロットを描け.

▼ 絶対値関数

関数 abs(x)は,$x$ の絶対値を返す.

using Plots
#gr() #pythonplot()
aux = (label="", lc=:black, lw=0.5)

plot(aspect_ratio=:equal)

xs = -1:0.1:1
plot!(xs, abs.(xs), label = "abs")
vline!([0]; aux...)

絶対値関数の符号を変えたり,平行移動すると,色々な山や谷の形を描くことができる.

using Plots
#gr() #pythonplot()
aux = (label="", lc=:black, lw=0.5)

plot(aspect_ratio=:equal)
plot!(framestyle=:zeroline)

xs = -2pi:pi/18:2pi
# 符号を変える.山の形
plot!(xs, -abs.(xs), label = "-abs(x)")
plot(xs, pi .- abs.(xs), label = "pi-abs(x)")
# さらに,横軸の平行移動
plot!(xs, pi .- abs.(xs .- pi), label = "pi-abs(x-pi)")
vline!([pi]; aux...)

plot!()

▼ クランプ関数

Base.Math.clamp

関数 clamp(x, lo, hi) は,上限と下限で制限する関数である. すなわち,$x$ の値が hi よりも大きければ hi を,lo よりも大きければ lo を返す. どちらでもなければ,そのままの値を返す.

using Plots
#gr() #pythonplot()
aux = (label="", lc=:black, lw=0.5)

plot(aspect_ratio=:equal)

xs = -5.0:0.1:5.0
plot!(xs, clamp.(xs,-1,2), label = "clamp")
hline!([-1,2]; aux...)
vline!([-1,2]; aux...)

■ 床関数・天井関数

床関数 floor(x) は,$x$ 以下の最大の整数を返す.

天井関数 ceil(x) は,$x$ 以上の最小の整数を返す.

下のプロットで,整数 $x$ に対する関数の値を,よく観察せよ.

これらの関数は,■ 浮動小数点数から整数への変換 で用いられる.

using Plots
#gr() #pythonplot()

aux = (label="", lc=:black, lw=0.5)
filledcircle=(
    seriestype=:scatter,
    shape=:circle, markershape=:circle, markerstrokewidth=0)

plot(palette=:Set1_9,aspect_ratio=:equal,
    size=(720,480))

xs = -3.4:0.2:3.4
xlims!(-3.5, 3.5)
ylims!(-3.5, 3.5)

scatter!(xs, ceil.(xs),  shape=:circle, mc=1, ms=4,
    label = "ceil")
scatter!(xs, floor.(xs), shape=:circle, mc=2,
    label = "floor")
vline!(-3:3; aux...)
hline!(-3:3; aux...)

▲ 練習

床関数または天井関数を用いて, 正の数を $1$ の位で四捨五入するには,どうしたらよいか? $1$ の位での四捨五入とは,その数の小数点第一桁目が $5$ 以上であれば元の数に $1$ を加え,$5$ 未満であれば何もしない操作である.

プログラムを書いて,プロットを描き,確認してみよ. とくに,小数点以下が $0.5$ に等しい場合の結果を観察せよ.

Note

数字のおおよその値を表すために日常用いられる「四捨五入」は,科学技術分野では適当な表し方ではない. 「数字の丸め方」は,日本工業規格 JIS Z8401 : 1999 (国際規格 ISO 31-0 : 1992 に相当)に定められている.JIS規格の全文は,たとえば,ここで読める.→ kikakurui Z8401-1999-01

▲ 練習

ここまで紹介した関数を使って,色々な不連続曲線や周期関数を描いてみよ. Jupyter notebookの Markdown セルを用いて,説明文も加えよ.

★ 今回のまとめ

  • plot 関数のフォーマットパラメータ
  • 0 による除算
  • 逆数関数
  • 不連続な有理関数
  • 正接・余接関数
  • 周期関数
  • 符号関数
  • 絶対値関数
  • 床関数・天井関数