やりたいこと
グラフを複数同じキャンバス(figureのほうが適切?)に描くとき、それぞれの線の色を変えたいですよね。
通常、PythonもJuliaも自動で色を変えてくれますが、それをきれいなグラデーションで少しづつ変化させるときれいです。
で、その方法はpythonだと簡単に見つかるんですが、Juliaだとなかなか見つからなかったので、記事にしようというわけです。
問題設定
f(x) = x^{n}, n = 1, 2, 3\cdots 10, x \in [-1, 1]
をプロットしたいとします。ただし、
- プロットは同じfigure中に描く
- nが変わったとき、色を変える
- 色は徐々に(連続的に)変化させる
としましょう。
最終的にこんなプロットができればゴールです。
Pythonだと
Python(正確にはmatplotlib)なら、以下のようにかける。
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm
x = np.linspace(-1,1,100)
N_max = 10
for n in range(1,N_max+1,1):
y = x**n
color = cm.viridis(float(n/N_max))
plt.plot(x,y, color=color, label = 'x to the {}th'.format(n))
plt.legend(loc=0)
ポイントは変化する指数$n$を$N_max$で割った値を、カラーマップスキームに引数として渡すところかと思う。
color = cm.viridis(0~1のfloatを与える)
こうすると、指定したカラーマップスキームの中から、色を0~1のスカラー値でピックアップすることができる。
Juliaだと
Julia(ここではPlots+GRやPlotlyを想定)だと少し難しくなる。
なぜかといえば、カラーマップスキームに引数として0~1のfloatを渡すことができないからである。
一応、カラーマップスキームはc=:[なにかのscheme]
で渡すことができるらしいので、試してみる。
# cを指定
# 違う、そうじゃない
x = LinRange(-1,1,100)
p = plot()
N_max = 10
for n in 1:N_max
y = map(xx-> xx^n, x)
p = plot!(p,x,y,
c=:viridis,
label= string("x to the ", n,"th" ),
legend=:bottomright)
end
display(p)
色が全部おなじになっちゃった(´;ω;`)
解決策
このExampleが解決策だった。
さきに解決策を書こう。
# cgradをうまくつかうのか〜
x = LinRange(-1,1,100)
p = plot()
N_max = 10
#ここで色の候補を作っておく
C(g::ColorGradient) = RGB[g[z] for z=LinRange(0,1,N_max)]
# colormap schemeの指定
g = :viridis
# 色のリスト作成(パイプ使用)
colorlist = cgrad(g) |> C
for n in 1:N_max
y = map(xx-> xx^n, x)
p = plot!(p,x,y, c=colorlist[n], # ここで色をピックアップ
label= string("x to the ", n,"th" ), legend=:bottomright)
end
display(p)
やったね。
何してるの
何してるんだろう。
正直な話、
#ここで色の候補を作っておく
C(g::ColorGradient) = RGB[g[z] for z=LinRange(0,1,N_max)]
は何が起きているのかよくわからない。
関数CをRGBのリストとして定義しているけれど、その中にColorGradient型のgがあって、そのスライスとしてzが使われていて、、、、
正直良くわからない¯_(ツ)_/¯
ただ、機能としては「指定のカラーマップ(g
)を N_max 分割して、そのリストを作る関数を作成」みたいなことをしている。
ポイントはこの関数の引数に直接gを指定しているのではなく、cgrad
関数の返り値を入れることである。
# colormap schemeの指定
g = :viridis
# 色のリスト作成(パイプ使用)
colorlist = cgrad(g) |> C
ここは実際にカラーマップスキームを指定して、色のリストを実際に作成している。
|>
はいわゆるパイプであることに注意。関数Cの引数としてcgrad(g)
の値が入っている。
## 最後に
Matplotlibだったらできるのに・・・というときには、BackendとしてPyPlot
使う手もあるわけだし、どうしても必要というわけではないかもしれないし、よくわかってないけど、とりあえずできたからヨシ!