グラフを描くには

Julia でグラフを描くツール(package)はたくさんあるが、まあ、とりあえずのおすすめとして “Plots” package とそのサブ package の “GR” の組み合わせをお勧めしておこう.

juliabox だったらこれらは既にインストールされているので、そのセッションで一回だけ

using Plots
gr()

とやっておけばよい.その後、そのセッション内では自由に(後述の) plot() 命令が使える.

私物PC のような環境の場合は、セッションごとに上の操作をする他、これらの package を(その PC について一回だけでよいが)インストールしておかないといけない. そうした場合のインストールは簡単で、

Pkg.add("Plots")
Pkg.add("GR")

とするだけでよい.
注: 上の話は Julia v0.6 までの話で、Julia v1.0 から GR は Plots にデフォルトで採用されているので Pkg.add("Plots") するだけで GR もインストールされる.

というわけで、まずはこの「使うよ宣言」をしておこう(私物 PC の人は、インストールを先にやっておこう).

1
2
using Plots  # plot 命令を使うセッションでは、この2行を一回だけ実行しておく.ちょっと待たされるよ.
gr()

Plots.GRBackend()

そして、Julia で基本的なグラフを描くには、plot 命令を使えば良い. おおよそ、

  • ベクトルを plot に渡すと、普通の 2次元グラフを描いてくれる
  • 行列を contour に渡すと(3次元データの)等高線グラフを、
    行列を wireframe に渡すと(3次元データの)立体ワイヤーフレームグラフを、
    行列を surface に渡すと(3次元データの)立体のきれいなグラフを、描いてくれる.
    (これらは、x軸ベクトル、y軸ベクトル、値行列、オプションの組を plot に渡す命令の省略形).

まずはそれっぽいベクトルを作ってみよう

1
v = [ n^2 for n in -2:0.1:2 ]  # -2 から 2 まで 0.1 おきに n という変数を作り、それを n^2, つまり二乗して並べたベクトル

41-element Array{Float64,1}: 4.0 3.61 3.24 2.89 2.56 2.25 1.96 1.69 1.44 1.21 1.0 0.81 0.64 ⋮ 0.81 1.0 1.21 1.44 1.69 1.96 2.25 2.56 2.89 3.24 3.61 4.0

このベクトル vplot 命令に渡してみよう

1
plot(v)  # plot 命令も、そのセッションで初めて動くときだけは遅いよ.すこし待とう.

plot

無事にグラフが描かれることがわかってもらえると思う.
基本はこのノリで、データをベクトル形式に突っ込んでそれを plot に渡せば良い.

グラフの各点にマーカーがあったほうが良いな、という場合は例えば次のようにすれば良い.

1
plot(v, marker = :auto)

plot_marker

ちなみにこうした情報は、Julia 自身のもつ内部マニュアルでひいていくことができる(英語だけどね). 今回は次のような感じでわかる.

1
?plot  # plot 命令について、尋ねてみる

search: plot plot! plotly plot3d Plots plot3d! plotlyjs plotattr plotarea The main plot command. Use plot to create a new plot object, and plot! to add to an existing one: plot(args…; kw…) # creates a new plot window, and sets it to be the current plot!(args…; kw…) # adds to the current plot!(plotobj, args…; kw…) # adds to the plot plotobj There are lots of ways to pass in data, and lots of keyword arguments… just try it and it will likely work as expected. When you pass in matrices, it splits by columns. To see the list of available attributes, use the plotattr([attr]) function, where attr is the symbol :Series:, :Subplot:, :Plot or :Axis. Pass any attribute to plotattr as a String to look up its docstring; e.g. plotattr("seriestype").

1
plotattr(:Series)  # とりあえず、最初にでてきたキーワード :Series について、上に書かれた通りに調べてみる.

Defined Series attributes are: arrow, bar_edges, bar_position, bar_width, bins, contours, fill_z, fillalpha, fillcolor, fillrange, group, hover, label, levels, line_z, linealpha, linecolor, linestyle, linewidth, marker_z, markeralpha, markercolor, markershape, markersize, markerstrokealpha, markerstrokecolor, markerstrokestyle, markerstrokewidth, match_dimensions, normalize, orientation, primary, quiver, ribbon, series_annotations, seriesalpha, seriescolor, seriestype, smooth, stride, subplot, weights, x, xerror, y, yerror, z

1
plotattr("markershape")  # マーカーの形状についてなにかわかりそうだ

markershape {Symbol, Shape, or AbstractVector} markershapes, shape Choose from Symbol[:none, :auto, :circle, :rect, :star5, :diamond, :hexagon, :cross, :xcross, :utriangle, :dtriangle, :rtriangle, :ltriangle, :pentagon, :heptagon, :octagon, :star4, :star6, :star7, :star8, :vline, :hline, :+, :x]. Series attribute, default: none

これによると、マーカーの形状を自分で指定することも簡単だ.例えば六角形でやってみると…

1
plot(v, marker = :hexagon)

0 10 20 30 40 0 1 2 3 4 y1

よく見ると確かに六角形がマーカーになっている.

さて、3次元グラフにもチャレンジしてみよう

1
A = [ x^2 + y^2 for x in -1:0.1:1, y in -1:0.2:1 ]  # x^2 + y^2 の値に相当する行列を作る

21×11 Array{Float64,2}: 2.0 1.64 1.36 1.16 1.04 1.0 1.04 1.16 1.36 1.64 2.0 1.81 1.45 1.17 0.97 0.85 0.81 0.85 0.97 1.17 1.45 1.81 1.64 1.28 1.0 0.8 0.68 0.64 0.68 0.8 1.0 1.28 1.64 1.49 1.13 0.85 0.65 0.53 0.49 0.53 0.65 0.85 1.13 1.49 1.36 1.0 0.72 0.52 0.4 0.36 0.4 0.52 0.72 1.0 1.36 1.25 0.89 0.61 0.41 0.29 0.25 0.29 0.41 0.61 0.89 1.25 1.16 0.8 0.52 0.32 0.2 0.16 0.2 0.32 0.52 0.8 1.16 1.09 0.73 0.45 0.25 0.13 0.09 0.13 0.25 0.45 0.73 1.09 1.04 0.68 0.4 0.2 0.08 0.04 0.08 0.2 0.4 0.68 1.04 1.01 0.65 0.37 0.17 0.05 0.01 0.05 0.17 0.37 0.65 1.01 1.0 0.64 0.36 0.16 0.04 0.0 0.04 0.16 0.36 0.64 1.0 1.01 0.65 0.37 0.17 0.05 0.01 0.05 0.17 0.37 0.65 1.01 1.04 0.68 0.4 0.2 0.08 0.04 0.08 0.2 0.4 0.68 1.04 1.09 0.73 0.45 0.25 0.13 0.09 0.13 0.25 0.45 0.73 1.09 1.16 0.8 0.52 0.32 0.2 0.16 0.2 0.32 0.52 0.8 1.16 1.25 0.89 0.61 0.41 0.29 0.25 0.29 0.41 0.61 0.89 1.25 1.36 1.0 0.72 0.52 0.4 0.36 0.4 0.52 0.72 1.0 1.36 1.49 1.13 0.85 0.65 0.53 0.49 0.53 0.65 0.85 1.13 1.49 1.64 1.28 1.0 0.8 0.68 0.64 0.68 0.8 1.0 1.28 1.64 1.81 1.45 1.17 0.97 0.85 0.81 0.85 0.97 1.17 1.45 1.81 2.0 1.64 1.36 1.16 1.04 1.0 1.04 1.16 1.36 1.64 2.0

さあ、プロットしてみよう.最初は contour (等高線表示になる)だ.

1
contour(A)

contour

tips: ちなみに、plot に行列 A だけを渡すと、(この場合は)「縦ベクトル11個のデータを一度に渡した」と解釈され、11個のグラフを同時描画する. これはこれで使えるテクニックなので覚えておこう.

1
plot(A)

5 10 15 20 0.0 0.5 1.0 1.5 2.0 y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 y11

次は wireframe だ.

web browser への負荷は高いが…

1
wireframe(A)

wireframe

最後は sufrace だ…が、juliabox だと下記のようにエラーになることがままある. これは個人ではどうしようもないので、ひとまずその場合は諦めておこう.

1
surface(A)

GR3 error (gr3.c, l. 153): init failed Stacktrace: [1] _check_error() at /home/jrun/.julia/v0.6/GR/src/gr3.jl:73 …略…

ちなみに、エラーにならないような環境ならば、次のような3次元図が得られる(これは通常の PC にインストールした julia で出力したもの).

surface

tips: wireframesurface などの 3次元プロットでは、camera = (平面角, 高さ角) というオプションをつけると、その位置にカメラを置いた表示にしてくれる. デフォルトは camera = (30,30) だ. ちなみに、平面角も高さ角も (なぜか) 0 から90までに制限されているようだ. 詳しくは plotattr("camera") とすると簡単なマニュアルが出るので読んでみよう.

ちなみに、下の画像はこの camera オプションを使ってみた例だ. デフォルトのものと、グラフを眺めている位置が異なるのが分かるだろう.

1
wireframe(A, camera=(22,58))

wireframe-with-camera-option

パラメータを変えて試行錯誤するときに便利なパッケージ Interact を使って、グラフを動かそう

package Interact についてはまた詳しくやるとして、ここでは以下のようにしてみよう.

まず一回だけ、Interact の使用宣言をする.

1
using Interact

それから、次のようにしてみよう. ちなみに、@manipulate が Interact が提供している命令で、ここで指定したパラメータが画面に「バー」となって操作できるように現れる. バーを掴んで動かしてみよう.

1
2
3
@manipulate for θ in 0:2:90, h in 0:2:90
  wireframe(A, camera=(θ,h))
end

bars

manipulate

簡易アニメーション

本格的なものについてはまた学ぶとして、上の camera オプションに絡めて、簡単なアニメーションをその場で作る方法も書いておこう. これは上の @manipulate にそっくりの使い方で、下記の例をやってみればわかるだろう.

tips: アニメーションを作るのには結構時間がかかるよ(この場合は2分程度).じっくり待とう.

1
2
3
@gif for θ in 15:2:75
    wireframe(A, camera=(θ,30))
end

gif-sample