JuliaでPlotsするよ

#はじめに
**Julia言語**で、数値データを手っ取り早くグラフとかに**可視化**するならば現状
`Plots` `Makie`の2択が有力ではないでしょうか。
今回はそのうち`Plots`を使ってみます

#Plotsって?
特徴として
・**複数のバックエンドを、ほぼ単一の記述で扱うことができる**

が上げられ、様々な特徴の可視化パッケージを、それぞれ個別に関数・記法を覚えていては無駄が多いので
*フロントエンド* として`Plots`で仕様を吸収し それら使用を気にすることなく*バックエンド*を扱う事ができます。

詳細は、[docs.juliaplots.org](http://docs.juliaplots.org/latest/)に詳しいです。
(以下の内容はほとんど、docsの内容となります。)


#バックエンド
扱える可視化パッケージ
それぞれ別個であるエンジンのJulia Wrapperのようです。
##

|バックエンド名|説明|
|---|---|
|`GR`|デフォルト・軽い|
|`Plotly`/`PlotlyJS`|キレイ・インタラクティブ(ブラウザ表示)|
|`PyPlot`|キレイ・インタラクティブ、PyCallを使ったMatplotlib|
|PGFPlotsX|Texによるグラフ生成（pkg以外に必要条件が多数あり未確認です・・）|
|`InspecterDR`|軽い、2D限定|
|`UnicodePlots`|REPL上でCUI表示、そりゃ軽い|
|`HDF5`|表示ではなく、「.hdf5」形式で可視化データをファイル操作する|

私は**普段**`GR`、見た目**キレイ**で`PyPlot`か、3Dで**グリグリ**で`Plotly`といったところです。

#準備
まだ`Plots`パッケージをいれてないなら、パッケージモードで

```julia
pkg>add Plots
#さらにGRを除く他のバックエンドが必要なら、 例：PyPlot
pkg>add PyPlot
```

と入れておきましょう
(pkgにより、更に追加のインストールがいる場合もあります。)

#使用例
###動作確認

```julia
using Plots
gr()           #バックエンドの指定・切り替え(デフォはGRなので、なくてもよい)
plot(sin)      #関数sinをプロット。　plot(関数;初期値,終了値)で初期値・終了値を省略したもの
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/6fc62d27-0090-e7ba-285c-e7aa861ae189.png" width="250">
とsin関数が表示されるはずです。(REPLからなら別窓)

以下、特に指定ないものはバックエンド`gr()`で`Jupyter notebook`出力です。
###プロットに追加
```julia
plot(sin) 
plot!(cos)  #関数cosを追加。　plot!((ベースのプロット,) 追加関数,...)　,ベース関数の省略時は直前のプロット
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/ae8657f9-ea0d-d2cf-af44-d11a2661426f.png" width="250">
追加は何度も重ねられます。
`p=plot(...)`で変数に残しておけば直前のもでなくても`plot!(p,関数,...)`で可能です。
また、`current()`で直前プロットを拾う事もできます。

###プロット内表示の調整
```julia
plot(x->(x^2-1),               #無名関数による x²-1
    xlabel       ="X_value",   #X軸のラベル
    ylabel       ="Y_value",   #Y軸のラベル
    label        ="LABEL",     #凡例のテキスト
    xlims        =(-3,3),      #X軸の範囲
    ylims        =(-3,3),      #Y軸の範囲
    aspect_ratio =0.5,         #表示のY/Xのアスペクト比
    title        ="TITLE",     #タイトル
    linecolor    =:blue,       #線の色
    linewidth    =5,           #線幅
    linestyle    =:dot,        #線種
    size         =(400,300),   #プロットのサイズ
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/1c28c994-a0c2-833c-500c-faace42a4927.png">
プロットの調整の**ごく一部**ですが、更にAlias等も沢山あります。
詳細は先ほどのdocsの**[Attributes](http://docs.juliaplots.org/latest/attributes/)**や**[supported Attributes](http://docs.juliaplots.org/latest/generated/supported/)**(対応/未対応)をちょくちょく確認しましょう。


毎回 同じような設定の場合は最初のバックエンド切替えで`gr(設定)`や`default(設定)`で宣言しておけば、手間が省けます。



###グラフの種類
入力するデータタイプにもよりますが、`seriestype`の指定で**グラフの種類**を変更できます。

```julia
#plot(データ配列,st=:グラフの種類,...) stはseriestypeのAlias
p1=plot(rand(50),st=:bar,title="bar")                           #棒グラフ
p2=plot(rand(5),st=:pie,title="pie")                            #円グラフ
x=0:0.2:10
p3=plot(x,exp.(-x),st=:scatter,title="scatter",label="exp(-x)") #散布図 plot(xデータ,yデータ,st=...)
p4=plot(rand(1000)+rand(1000)+rand(1000)+rand(1000),
        st=:histogram,title="histogram")                        #ヒストグラム(4回乱数を足したデータを自動処理)
plot(p1,p2,p3,p4,layout=(1,4),size=(1000,300))                  #上記プロットを一気に1×4レイアウトでプロット
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/cc387bf4-de59-5621-1e07-a114e2547bff.png)

docsによると
`:none`,` :line`,` :path`,` :steppre`,` :steppost`,` :sticks`,` :scatter`,` :heatmap`,` :hexbin`,` :barbins`,` :barhist`,` :histogram`,` :scatterbins`,` :scatterhist`,` :stepbins`,` :stephist`,` :bins2d`,` :histogram2d`,` :histogram3d`,` :density`,` :bar`,` :hline`,` :vline`,` :contour`,` :pie`,` :shape`,` :image`,` :path3d`,` :scatter3d`,` :surface`,` :wireframe`,` :contour3d`,` :volume`
と種類があるようです。

この辺りのいくつかは`st=`で指定しなくても、**そのままの関数**が用意されており

```julia
#データ作成
x=-3:0.2:3
y=x
z=@. exp(-(x^2+y'^2))                                    #z=exp(-(x²+y²)) , yの[']転置と@.マクロに注意
#各プロット
p1=heatmap(z,title="heatmap")                            #ヒートマップ heatmap(2次元データ,...)
p2=contour(x,y,z,title="contour")                        #コンター図   contour(xデータ,y,z,...)
p3=wireframe(x,y,z,title="wireframe")                    #3Dのワイヤーフレーム表記
p4=surface(x,y,z,title="surface")                        #3Dの曲面表示
plot(p1,p2,p3,p4,layout=(1,4),size=(1500,250),fmt=:png)  #1×4表記 (少し重たくなるので、後述のフォーマットpng)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/367a74eb-e8aa-1c53-7ec7-d76d187d2017.png)
とプロットできます。
上記のデータ入力は一例で、複素数データを2D極座標で表示してくれたりなど柔軟さがあります。
これもdocsの[**Input Data**](http://docs.juliaplots.org/latest/input_data/)を確認するとよいでしょう。


###出力形式(pngとsvg)
先ほどの`plot`で`fmt=:png` を指定しましたが、デフォルでは`:svg`形式で出力されます。
`:png`は画像形式ですが、`:svg`は座標等の描画情報を持っており、`wireframe`プロット等したとき
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/e789298d-073e-b800-f94a-6baeb3499648.png" width="300">
の様に、`Jupyter`ではブラウザが頑張って線を引き、**動作が重たくなってしまう**場合があります。
また、大概の例で`:svg`の方が**表示はキレイ**なのですが、`PyPlot`バックエンドの`heatmap`で
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/ae48d7a4-d5ee-222c-d147-44d50f8a2af0.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/2189b29d-3dc0-c7ac-39c5-74e0ebc9286d.png)
の様に**妙な線が入ってしまう**場合があるので、場合によって使い分けるといいと思います。

##カラースキーム
レンジ色のカラースキームを調整します。
`seriescolor`を指定しますが、細かくは`palette` `cgrad`関数で指定します。

```julia
#plot(データ配列,c=:カラースキームの種類,...) colorはseriescolorのAlias（他にc等)
x=y=range(-10,10,length=51)
r(x,y)=sqrt(x^2+y^2+0.0)+1e-10
z(x,y)=sin(r(x,y))/r(x,y)

p1=surface(x,y,z.(x,y'),color=palette(:ice    ,10) ,title="palette(:ice,10)")     #パレットに:ice指定(2番目の引数は分割数)
p2=surface(x,y,z.(x,y'),color=palette(:thermal,10) ,title="palette(:thermal,10)") #パレットに:thermal指定
p3=surface(x,y,z.(x,y'),color=cgrad(:thermal)      ,title="cgrad(:thermal)")      #グラデーションで:thermal指定
p4=surface(x,y,z.(x,y'),color=:thermal             ,title=":thermal")             #省略表記は上記グラデーション

plot(p1,p2,p3,p4,layout=(2,2),size=(1500,600))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/8f68b1a9-4698-df3d-0003-1beee39b9588.png)
余り代り映えしていませんが、カラースキームが変更されています。
他に`:rainbow` `:blues` `:Spectral`など、docsの[colorschemes](http://docs.juliaplots.org/latest/generated/colorschemes/)で確認できます。


また、上記の`palette` `cgrad`関数は自分で色を指定して(`RGB`可)、単体で出力確認もできます。

```julia
palette([:red,:white,:purple],15 ,rev=true) |>display   # rev=trueは反転
cgrad([RGB(255/255,0,0),:lightgreen])       |>display   # RGB関数は各色0～1範囲
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/61eb41eb-b439-839a-b14f-b71a6a7932dd.png)

線色等でも使ってましたが、[X11の色名称(Wikipedia)](https://ja.wikipedia.org/wiki/X11%E3%81%AE%E8%89%B2%E5%90%8D%E7%A7%B0)をサポートしている様で、なんとなく入れて作りたいものが大体できるでしょう。


##動画の出力
**出力したプロット**をpng形式でtmpフォルダに保存し、**ffmpegに投げる**ようです。
~~その為`Julia`とは別に`ffmpeg`のインストールと`PATH`を通しておく必要があります。~~
(古いverの認識でした。現在は自動で入るようです。コメント欄参照、感謝)

####gif動画の生成

```julia
anim = @animate for i in 0:0.1:2　　　　　　　　　　　　#@animateマクロでfor文内ループ毎をフレームとしたpngファイル生成
    x=0:0.1:2
    y1=@. sin(pi*(x+i))
    y2=@. cos(pi*(x+i))
    plot(x,y1,label="sin(π(x+$i))",size=(250,250))   #ラベルのテキストに$(変数)を使う事でラベル表示も変化
    plot!(x,y2,label="cos(π(x+$i))")                 #最後のプロットがpngとして格納される
end                                                  #endの後にever 5 等とすると5フレーム毎に残す
gif(anim,fps=30,"sin_cos.gif")                       #gif出力,fpsとファイル名指定はオプション(tmp.gifがデフォ)
```

![index.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366073/1fd017a1-acbc-5454-b9e9-a19d14f19aed.gif)

`gif()`以外にも他にも`mp4()`,`mov()`,`webm()`あるようです。

**動画生成は**長めに作ると完成まで時間がかかり、確認が**遅くなる**のですが`Jupyter notebook`での動画に限り
・[**JuliaのJupyterでプロット動画を素早く確認する**#折衷案](https://qiita.com/I_ppp/items/d0999d33d5af42b926e4#%E6%8A%98%E8%A1%B7%E6%A1%88)
を利用すると、各フレームを**プロット出力しながら**の確認にすることができます。

#機能さがし(追記)
docsを見るのが一番ですが

```julia
plotattr(:Plot)
plotattr(:Series)
plotattr(:Subplot)
plotattr(:Axis)
```
とすることで、それぞれのattributes一覧が出力されます

```julia
Defined Plot attributes are:
background_color, background_color_outside, display_type, dpi, extra_kwargs, extra_plot_kwargs, fontfamily, foreground_color, html_output_format, inset_subplots, layout, link, overwrite_figure, plot_title, plot_title_location, plot_titlefontcolor, plot_titlefontfamily, plot_titlefonthalign, plot_titlefontrotation, plot_titlefontsize, plot_titlefontvalign, pos, show, size, tex_output_standalone, thickness_scaling, warn_on_unsupported, window_title
Defined Series attributes are:
arrow, bar_edges, bar_position, bar_width, bins, colorbar_entry, connections, contour_labels, contours, extra_kwargs, 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, normalize, orientation, primary, quiver, ribbon, series_annotations, seriesalpha, seriescolor, seriestype, show_empty_bins, smooth, stride, subplot, weights, x, xerror, y, yerror, z, zerror
Defined Subplot attributes are:
annotations, aspect_ratio, background_color_inside, background_color_legend, background_color_subplot, bottom_margin, camera, clims, color_palette, colorbar, colorbar_fontfamily, colorbar_title, colorbar_title_location, colorbar_titlefontcolor, colorbar_titlefontfamily, colorbar_titlefonthalign, colorbar_titlefontrotation, colorbar_titlefontsize, colorbar_titlefontvalign, extra_kwargs, fontfamily_subplot, foreground_color_legend, foreground_color_subplot, foreground_color_title, framestyle, left_margin, legend, legendfontcolor, legendfontfamily, legendfonthalign, legendfontrotation, legendfontsize, legendfontvalign, legendtitle, legendtitlefontcolor, legendtitlefontfamily, legendtitlefonthalign, legendtitlefontrotation, legendtitlefontsize, legendtitlefontvalign, margin, projection, right_margin, subplot_index, title, titlefontcolor, titlefontfamily, titlefonthalign, titlefontrotation, titlefontsize, titlefontvalign, titlelocation, top_margin
Defined Axis attributes are:
discrete_values, draw_arrow, flip, foreground_color_axis, foreground_color_border, foreground_color_grid, foreground_color_guide, foreground_color_minor_grid, foreground_color_text, formatter, grid, gridalpha, gridlinewidth, gridstyle, guide, guide_position, guidefontcolor, guidefontfamily, guidefonthalign, guidefontrotation, guidefontsize, guidefontvalign, lims, link, minorgrid, minorgridalpha, minorgridlinewidth, minorgridstyle, minorticks, mirror, rotation, scale, showaxis, tick_direction, tickfontcolor, tickfontfamily, tickfonthalign, tickfontrotation, tickfontsize, tickfontvalign, ticks, widen
```
aliasではないので、機能名前っぽいはずです。
ここから欲しい感じのを探して更に

```julia
plotattr("camera")
```

```julia
camera {NTuple{2, Real}}
cam, cameras, view_angle, viewangle

Sets the view angle (azimuthal, elevation) for 3D plots
Subplot attribute,  default: (30, 30)
```
と docsと同様の内容ですが、aliasと機能が分かるで当たりをつけて探しやすくなると思います。
（他にいい方法があるなら教えてほしい）



#その他
###時間短縮
**表示までが遅い**と思った人もいるかもしれません。
`Plots`は巨大パッケージで、初回のJITコンパイルが結構長めです。対策としては、`PackageCompiler`をもちいるのが有力で
・[**PackageCompiler.jlでPlotsの呼び出しを高速化する2020年7月版**](https://qiita.com/cometscome_phys/items/85150cca4e4ff7c1d568)
が参考になります。
（オプションで、更に`precompile`する関数の指定も可能なのですが、やりすぎると表示されない謎動作等が多発します・・・）

 ~~また現在(2020年8月)は`Julia`の安定版はver`1.5.0`で、これまでも高速化されてきましたが
・**Nightly builds**`1.6.0-dev`では**大幅に高速化**
といった情報もあるので**期待** and **試してみる**とよいと思います。~~
(2021年4月)`1.6.0`安定版でましたね。`1.5.0`の頃から2倍近く早くなってんじゃないでしょうか
Juliaは最新版で結構安定しているので、随時更新すると良いと思います。


#### 機能しない等エラーについて(2021年08月追記)
`Plots`まわりは複雑で上手く機能が動かない事もあるのですが、デフォルトのバックエンド`GR`要因が多々あるようです。
下記コメント欄、プロットサイズがおかしい問題などは`GR`versionが古い場合がある様なのでパッケージモードで
`pkg> up GR`で解決するかもしれません。
また、別のバックエンド指定(特に`PyPlot`)ではちゃんと機能したりする場合、`GR`は諦めた方が早いかもしれません。