LoginSignup
4
3

More than 3 years have passed since last update.

Juliaで色を徐々に変えながらプロットする方法

Posted at

やりたいこと

グラフを複数同じキャンバス(figureのほうが適切?)に描くとき、それぞれの線の色を変えたいですよね。
通常、PythonもJuliaも自動で色を変えてくれますが、それをきれいなグラデーションで少しづつ変化させるときれいです。
で、その方法はpythonだと簡単に見つかるんですが、Juliaだとなかなか見つからなかったので、記事にしようというわけです。

問題設定

 f(x) = x^{n},  n = 1, 2, 3\cdots 10, x \in [-1, 1]

をプロットしたいとします。ただし、

  • プロットは同じfigure中に描く
  • nが変わったとき、色を変える
  • 色は徐々に(連続的に)変化させる

としましょう。
最終的にこんなプロットができればゴールです。
goal.png

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)

byMatplotlib.png

ポイントは変化する指数$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)

mistake.png

色が全部おなじになっちゃった(´;ω;`)

解決策

この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)

goal.png

やったね。

何してるの

何してるんだろう。
正直な話、

#ここで色の候補を作っておく
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使う手もあるわけだし、どうしても必要というわけではないかもしれないし、よくわかってないけど、とりあえずできたからヨシ!

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3