プログラミング/julia/グラフの書き方

(768d) 更新


プログラミング/julia

目次

Plots を使う

関数グラフの描画には Plots というライブラリを使う。

これは様々なグラフ描画ライブラリを julia から同一の API で使えるようにするためのラッパーライブラリ。

実際の描画を行う Backend の描画ライブラリとして何を選ぶかによって、描画速度や仕上がりなどが大きく変わってくる。

インストール

バックエンドのライブラリがないと描画できないので、とりあえず GR も入れておく。

LANG:julia
Pkg.add("Plots")
Pkg.add("GR")

# github の最新版を使うには次のようにする
Pkg.checkout("Plots")

バックエンドライブラリ

実際の描画を行うバックエンドライブラリはいろいろある。

http://docs.juliaplots.org/latest/backends/

例えばバックエンドライブラリとして GR を使うには次のようにする。

LANG:julia
using Plots    // Plots ライブラリの関数を取り込む
Plots.gr()     // Plots のバックエンドとして GR を使うことにする
gr()           // using してあるので、こう書いても同じことになる

plot()         // GR を使ったグラフが出力される

たぶん、2018春時点で有名なのは GR, Plotly, PyPlot の3つ。

PGFPlots や GLVisualize もまずまず?

各ライブラリの対応表はこちら:
http://docs.juliaplots.org/latest/supported/

それぞれの特徴を独断と偏見でまとめると:

  • GR : Plots.gr()
    • 出力が svg になるので、印刷したときキレイ
    • 点がたくさんあるとブラウザが固まる
    • 普段使いにはこれがベスト?
    • 3D 表示の一部で x, y パラメータ指定の仕様が他と異なる? surface や wireframe
    • 3D 表示の一部に OpenGL を使うため物理ディスプレイなしでは使いづらい? → juliabox でも動かない

  • Plotly : Plots.plotly()
    • マウスでグラフの表示範囲などを調整可能
    • 特に3D表示をぐりぐり動かせるのは圧巻
    • 出力が svg になるので、印刷してもキレイ
    • 点がたくさんあるとブラウザが固まる
    • Gists 上などでは javascript が許可されないためまるっきり表示されない
    • jupyter notebook のリロードでもエラーになり画像が表示されない(場合がある?)
    • 試行錯誤中は良いのだが、最終版としてはつらい

  • PyPlot : Plots.pyplot()
    • 出力が png になるため、データ点の多いグラフでも Web ブラウザに負担がかからない
    • ただ印刷などすると dpi 不足で画像が粗くなりがち
    • インストール時に PyCall の設定が必要(下記参照)
    • 一番安定している気がする
    • GR が不得意とする 3D 表示や点数の多いグラフではこれがいい

  • PGFPlots : Plots.pgfplots()
    • 出力が svg になるので、印刷してもキレイ
    • 点がたくさんあるとブラウザが固まる
    • 3D は対応していないものが多い
    • 出力がキレイ(なのか?)

  • GLVisualize : Plots.glvisualize()
    • OpenGL を使うので高速(?)
    • 対応する機能が多い(?)
    • ディスプレイドライバが OpenGL に対応していなければならない
    • 物理ディスプレイのない環境で動かすのは大変そう(まだ動かせてない)

表示例

それぞれの表示はこんな感じ。

  • PyPlot は一番問題が少ないが、出力は png なので拡大すると粗い
  • GD は Surface プロットができない
  • Plotly は layout でグラフを複数並べると円グラフや3Dグラフの表示がおかしくなる
    • 単体なら問題ない
  • PGFPlots は Surface, Pie, WireFrame, HeatMap プロットができない

共通コードはこちら:
 各種グラフを書くためのコードサンプルになるはず。

LANG:julia
using Plots

data1d=rand(10)
data1d2=rand(10)
data1d3=rand(10)
data2d=[rand()/5 + exp(-(x^2+y^2)/100) for x in -10:10, y in -10:10]
data1dp=0:2pi/10:2pi;

function example(no3d=false,forpgf=false)
    plot(
        plot(data1d),
        plot(data1d,xscale=:log10,yscale=:log10),
        plot(data1d,seriestype=:steppre),
        plot(data1d,seriestype=:step),
        plot(data1d,seriestype=:scatter),
        plot(data1d,seriestype=:bar),
        forpgf ? plot() : plot(data1d,seriestype=:pie),
        plot(data2d,seriestype=:contour,legend=:none),
        plot(data2d,seriestype=:contour,fill=true,legend=:none),
        no3d ? plot() : plot(data2d,seriestype=:surface,legend=:none),
        forpgf ? plot() : plot(data2d,seriestype=:wireframe),
        forpgf ? plot() : plot(data2d,seriestype=:heatmap,legend=:none),
        plot(data1dp,data1d,proj=:polar),
        plot(data1d,data1d2,data1d2,seriestype=:scatter3d),
        plot(data1d,data1d2,data1d2),
        plot([0,1,0,-1],[-1,0,1,0],seriestype=:shape),
        layout=(4,4),size=(800,800),legend=:none
    )
end

PyPlot

test-julia-pyplot.png

GR

test-julia-gr.png

Plotly

test-julia-plotly.png

あまりにひどいので、表示のおかしなものをすべて取り去ったところこうなった。

test-julia-plotly2.png

複数グラフを layout で並べて表示するのが不得意なだけで、 ここでおかしかったものも単体で表示する分にはまともに表示される。

対数スケールの軸がキレイに表示されているのは Plotly だけだった。

PGFPlots

test-julia-pgfplots.png

svg vs png

GR のグラフは拡大してもキレイ

test-julia-plots-gr.png

PyPlot のグラフは拡大するとぼやける

test-julia-plots-pyplot.png

Plotly のグラフはインタラクティブに編集できるが・・・

ぐりぐり動く。

test-julia-plots-plotly.gif

test-julia-plots-plotly2.gif

でも、ブラウザ上でリロードするだけで、

Javascript error adding output!

ReferenceError: Plotly is not defined

See your browser Javascript console for more details.

などというエラーが出てグラフが表示されなくなってしまう。

Gist 上でも無理。

nbviewer でもダメだった。

http://nbviewer.jupyter.org/gist/osamutake/88c0d0676fe659df23769d2bdbcc21b6

gist から nbviewer への飛び方

ちょっとオフトピだけど・・・

gist 上で .ipynb を見たとき、右上に θ マークが表示されている場合があり、 そこにカーソルを合わせると nbviewer へのリンクが出るのだけれど、

gist-to-nbviewer.png

これをクリックしてもうまく nbviewer に繋がらない。

本来なら

http://nbviewer.jupyter.org/gist/osamutake/da4856f49e025e4646214a0ce690ba06

へ飛ぶべきが、

http://nbviewer.jupyter.org/github/osamutake/da4856f49e025e4646214a0ce690ba06/blob/9c7f6f6d2adc84c7dc78fa9874b22aa05b7d10cc/test-julia-plots.ipynb

へ飛んでしまう。

たぶん、github に入れた .ipynb ファイルからだとうまく行くんだと思う。

github の文字を gist に直し、/blob/ 以下を削除すれば良いのだけれど、 もっと簡単には http://nbviewer.jupyter.org/ に gist の URL を入れることで本来のページに飛べる。

バックエンドライブラリのインストール

結構いろいろ大変。
先人達の足跡を探すのに非常に時間がかかる。。。

GR のインストール

LANG:console
$ julia
julia> Pkg.add("GR")

これだけでOK

GLVisualize のインストール

Web ブラウザから jupyter 経由で使えるようにインストールしたかったのですが、現時点ではできてません。

LANG:console
$ julia
julia> Pkg.add("GLVisualize ")
 ...
  -- Could NOT find Vulkan (missing:  VULKAN_LIBRARY VULKAN_INCLUDE_DIR) 
  -- Using X11 for window creation
  ...
  CMake Error at CMakeLists.txt:222 (message):
   The RandR library and headers were not found
julia>^D

OpenGL が必要らしい。

LANG:console
$ sudo apt-get install libgl1-mesa-dev
 パッケージリストを読み込んでいます... 完了
 依存関係ツリーを作成しています
 状態情報を読み取っています... 完了
 以下のパッケージが自動でインストールされましたが、もう必要とされていません:
   libdmx-dev libdmx1 libfontconfig1-dev libfontenc-dev libfreetype6-dev libfs-dev libfs6 libice-dev
   libmirclient-dev libmircommon-dev libmircookie-dev libmircookie2 libmircore-dev libpciaccess-dev
   libpixman-1-dev libprotobuf-dev libprotobuf9v5 libsm-dev libxaw7-dev libxcomposite-dev libxcursor-dev
   libxfont-dev libxfont1-dev libxfont2 libxft-dev libxi-dev libxinerama-dev libxkbcommon-dev
   libxkbfile-dev libxmu-dev libxmu-headers libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev
   libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86dga-dev
   mir-client-platform-mesa-dev x11proto-bigreqs-dev x11proto-composite-dev x11proto-dmx-dev
   x11proto-dri3-dev x11proto-fonts-dev x11proto-present-dev x11proto-randr-dev x11proto-record-dev
   x11proto-render-dev x11proto-resource-dev x11proto-scrnsaver-dev x11proto-video-dev
   x11proto-xcmisc-dev x11proto-xf86bigfont-dev x11proto-xf86dga-dev x11proto-xf86dri-dev
   x11proto-xinerama-dev xserver-xorg-dev
 これを削除するには 'sudo apt autoremove' を利用してください。
 以下の追加パッケージがインストールされます:
   libdrm-amdgpu1 libdrm-common libdrm-dev libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2
   libgl1-mesa-glx libglapi-mesa mesa-common-dev
 以下のパッケージが新たにインストールされます:
   libdrm-common
 以下のパッケージはアップグレードされます:
   libdrm-amdgpu1 libdrm-dev libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2 libgl1-mesa-dev
   libgl1-mesa-glx libglapi-mesa mesa-common-dev
 アップグレード: 10 個、新規インストール: 1 個、削除: 0 個、保留: 26 個。
 1,062 kB のアーカイブを取得する必要があります。
 この操作後に追加で 616 kB のディスク容量が消費されます。
$ julia
julia> Pkg.build("GLVisualize ")

として試したところ、

X11: The DISPLAY environment variable is missing

と言うエラーが出た。

ディスプレイドライバの OpenGL 機能を使ってレンダリングするので、 Web サーバー経由の jupyter からは使えないのかもしれない?

https://github.com/JuliaGL/GLVisualize.jl/issues/146

VirtualGL を使えばできるのかもしれないけれど、ちょっと追い切れなかった。

Plotly のインストール

juliabox ならそのまま使えるのだけれど、 以下は自分で建てた jupyter サーバーにインストールする場合の話。

https://qiita.com/deaikei/items/b71c1ca2c4c2a2c37526 を見ながら。

julia 上で

LANG: julia
Pkg.add("Plotly")

とする前に、python の plotly モジュールを入れておかないとダメ。

LANG:console
$ python3 -m pip install plotly
$ julia
julia> Pkg.add("Plotly")

こうするのが正解。

PyPlot のインストール

juliabox ならそのまま使えるのだけれど、 以下は自分で建てた jupyter サーバーにインストールする場合の話。

正しい手順はこちら > #e720f643

試行錯誤

matplotlib を使うので、

LANG:console
$ sudo python3 -m pip install matplotlib

とすれば、python から使うのは簡単だった。

julia から使うには、単に Pkg.add("PyPlot") しただけだと、

InitError: Failed to import required Python module matplotlib.

For automated matplotlib installation, try configuring PyCall to use the Conda.jl package's Python "Miniconda" distribution within Julia. Relaunch Julia and run:
    ENV["PYTHON"]=""
    Pkg.build("PyCall")
before trying again.

The pyimport exception was: PyError (ccall(@pysym(:PyImport_ImportModule), PyPtr, (Cstring,), name)

The Python package matplotlib could not be found by pyimport. Usually this means
that you did not install matplotlib in the Python version being used by PyCall.

PyCall is currently configured to use the Python version at:

python

and you should use whatever mechanism you usually use (apt-get, pip, conda,
etcetera) to install the Python package containing the matplotlib module.

One alternative is to re-configure PyCall to use a different Python
version on your system: set ENV["PYTHON"] to the path/name of the python
executable you want to use, run Pkg.build("PyCall"), and re-launch Julia.

Another alternative is to configure PyCall to use a Julia-specific Python
distribution via the Conda.jl package (which installs a private Anaconda
Python distribution), which has the advantage that packages can be installed
and kept up-to-date via Julia.  As explained in the PyCall documentation,
set ENV["PYTHON"]="", run Pkg.build("PyCall"), and re-launch Julia. Then,
To install the matplotlib module, you can use `pyimport_conda("matplotlib", PKG)`,
where PKG is the Anaconda package the contains the module matplotlib,
or alternatively you can use the Conda package directly (via
`using Conda` followed by `Conda.add` etcetera).

) <type 'exceptions.ImportError'>
ImportError('No module named matplotlib',)


during initialization of module PyPlot

Stacktrace:
 [1] pyimport_conda(::String, ::String, ::String) at /home/osamu/.julia/v0.6/PyCall/src/PyCall.jl:609
 [2] __init__() at /home/osamu/.julia/v0.6/PyPlot/src/init.jl:175
 [3] _include_from_serialized(::String) at ./loading.jl:157
 [4] _require_from_serialized(::Int64, ::Symbol, ::String, ::Bool) at ./loading.jl:200
 [5] _require_search_from_serialized(::Int64, ::Symbol, ::String, ::Bool) at ./loading.jl:236
 [6] _require(::Symbol) at ./loading.jl:441
 [7] require(::Symbol) at ./loading.jl:405
 [8] include_string(::String, ::String) at ./loading.jl:522

と言われ、PyCall を build する必要があった。

正しい手順

LANG:console
$ sudo python3 -m pip install matplotlib
$ julia
julia> Pkg.add("PyPlot")
julia> ENV["PYTHON"]=""
julia> Pkg.build("PyCall")

ENV["PYTHON"]="" はシステムの python を使うためのおまじないっぽい?

PGFPlots のインストール

GR, Plotly, PyPlot は juliabox でもそのまま使えるのだけれど、 PGFPlots は juliabox では使えないため、使いたければ自分で建てた jupyter サーバーにインストールするしかない。

正しい手順はこちら > #beed29ca

試行錯誤

jupyter の上から Pkg.add("PGFPlots") としたところ、途中で

Installing dependency libmagickwand-6.q16-2 via `sudo apt-get install libmagickwand-6.q16-2`:

sudo: 端末 (tty) が存在せず、パスワードを尋ねる (askpass) プログラムが指定されていません
=============================[ ERROR: ImageMagick ]=============================

LoadError: failed process: Process(`sudo apt-get install libmagickwand-6.q16-2`, ProcessExited(1)) [1]
while loading /home/osamu/.julia/v0.6/ImageMagick/deps/build.jl, in expression starting on line 122

というエラーが出た。 そこでコンソールからやってみたら、

LANG:console
$ julia
julia> Pkg.build("PGFPlots")
 INFO: Building SpecialFunctions
 INFO: Building FFTW
 INFO: Building ImageMagick
 Installing dependency libmagickwand-6.q16-2 via `sudo apt-get install libmagickwand-6.q16-2`:
 [sudo] osamu のパスワード:
 パッケージリストを読み込んでいます... 完了
 依存関係ツリーを作成しています
 状態情報を読み取っています... 完了
 以下の追加パッケージがインストールされます:
   ghostscript gsfonts imagemagick-common libcupsfilters1 libcupsimage2 libgs9 libgs9-common libijs-0.35 libjbig2dec0 liblqr-1-0 libmagickcore-6.q16-2 libpaper-utils libpaper1
   poppler-data
 提案パッケージ:
   ghostscript-x hpijs fonts-droid texlive-lang-cjk libmagickcore-6.q16-2-extra poppler-utils fonts-arphic-ukai fonts-arphic-uming fonts-nanum
 以下のパッケージが新たにインストールされます:
 ghostscript gsfonts imagemagick-common libcupsfilters1 libcupsimage2 libgs9 libgs9-common   libijs-0.35 libjbig2dec0 liblqr-1-0 libmagickcore-6.q16-2 libmagickwand-6.q16-2
   libpaper-utils libpaper1 poppler-data
 アップグレード: 0 個、新規インストール: 15 個、削除: 0 個、保留: 20 個。
 12.1 MB のアーカイブを取得する必要があります。
 この操作後に追加で 48.1 MB のディスク容量が消費されます。
 続行しますか? [Y/n] 中断しました。
 ===============================================================================[ ERROR: ImageMagick ]===============================================================================
 
 LoadError: failed process: Process(`sudo apt-get install libmagickwand-6.q16-2`, ProcessExited(1)) [1]
 while loading /home/osamu/.julia/v0.6/ImageMagick/deps/build.jl, in expression starting on line 122
 
 ====================================================================================================================================================================================
 INFO: Building CodecZlib
 
 ==================================================================================[ BUILD ERRORS ]==================================================================================
 
 WARNING: ImageMagick had build errors.
 
  - packages with build errors remain installed in /home/osamu/.julia/v0.6
  - build the package(s) and all dependencies with `Pkg.build("ImageMagick")`
  - build a single package by running its `deps/build.jl` script
 
 ====================================================================================================================================================================================

となって、やはりエラー。おしい。

LANG:console
$ sudo apt-get install libmagickwand-6.q16-2
$ julia
julia> Pkg.build("PGFPlots")

で入った。

でも、plot を呼ぶと

Error saving as SVG

could not spawn `lualatex --enable-write18 --output-directory=. tikzpicture`: no such file or directory (ENOENT)

とのエラー。texlive-luatex を入れれば良いのかと思ったのだけれど、

LANG:console
$ sudo apt-get install texlive-luatex
$ lua^T
 lua2dox_filter   luajittex        luaotfload-tool  luatex

で、lualatex というコマンドは入らなかった?

http://mickey-happygolucky.hatenablog.com/entry/2016/03/01/234228 を見て、

LANG:console
$ sudo apt-get install texlive-lang-cjk lmodern texlive-xetex
$ which lualatex
 /usr/bin/lualatex

これでエラーメッセージが変わって、

Error saving as SVG

could not spawn `pdf2svg tikzpicture.pdf tikzpicture.svg`: no such file or directory (ENOENT)

そこで、

LANG:console
$ sudo apt-get install pdf2svg

これで正しく動作するようになった。

正しい手順

LANG:console
$ sudo apt-get install libmagickwand-6.q16-2 texlive-luatex texlive-lang-cjk lmodern texlive-xetex pdf2svg
$ julia
julia> Pkg.add("PGFPlots")

こうかな。

Plots.plot に関数を与えるだけでグラフを書ける

あまり用例を見ないのだけれど、直接関数を与えてグラフが書ける。とても便利。

plot-function1.png

plot-function2.png

ただ今のところ、グラフがカクカクになってしまったときにサンプリング点数を増やす方法が分からなくて困ってる。

@manipulate でインタラクティブにパラメータを変えられる

Interact モジュールと widget/extension を使う。

実際には、あらかじめパラメータを変えたグラフをすべて用意しておき、 入力値に従って切り替えて表示しているっぽい。

jupyter-interact.gif

@gif で手軽に GIF アニメが作れる

@gif を使ってアニメーションをしようとしたところ、

could not spawn `ffmpeg -v 0 -i /tmp/tmpsIoz72/%06d.png -vf palettegen=stats_mode=diff -y /tmp/tmpsIoz72/palette.bmp`: no such file or directory (ENOENT)

と言われた

LANG:console
$ sudo apt-get install ffmpeg

@recipe について

勉強せねば。

https://github.com/JuliaPlots/PlotDocs.jl/blob/master/docs/src/recipes.md

関数のグラフをキレイに描くためのモジュールを作った

http://nbviewer.jupyter.org/gist/osamutake/9fa7918013c1af17c50666bafb3469d0

funcplot.png

このあたりを見る?

Plots/GR: グラフ package のおすすめ
http://www.cas.cmc.osaka-u.ac.jp/~paoon/misc/julia/post/trouble-plots-package/

JupyterでJuliaを動かして回帰分析をやってみる。
https://qiita.com/kenmatsu4/items/b77ecec75418cbaa2212

jupyter notebookで触れるプロットを描く
http://ksknw.hatenablog.com/entry/2016/08/04/233103

Julia言語と Plots + GR で複素関数のgifアニメーションを作る
http://optie.hatenablog.com/entry/2018/03/29/210619

GR - examples
http://docs.juliaplots.org/latest/examples/gr/

PlotThemes
https://github.com/JuliaPlots/PlotThemes.jl

PGFPlots.ipynb
http://nbviewer.jupyter.org/github/sisl/PGFPlots.jl/blob/master/doc/PGFPlots.ipynb

コメント・質問




Research on tutorials you can use for your site

Vinay Tomar? ()

Hey,

I’ve been an avid reader of https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%2Fjulia%2F%E3%82%B0%E3%83%A9%E3%83%95%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9 for quite some time now – and I really love how detailed and well-researched your guides are.

I can only imagine the time you spent working on those.
Anyway, I noticed that you’ve been writing a lot about python lately. I have a resource on learning Python that talks about exactly that.

Guru99 has a huge list of software learning library across topics like Linux, Java ,PHP ,SQL ,Ethical Hacking, python any more with new courses added every month.

In this Python for beginners tutorial, you will learn Python installation, variables, Data structure, loops, strings, functions, file handling, Python SciPy, Python JSON, Python with MySQL, matrix, Python List, Python Regex, PyTest, PyQt, multithreading, Python interview questions, and many more interesting Python concepts.

You can see the full Python tutorial here: https://www.guru99.com/python-tutorials.html

I think mentioning it would bring some extra value for your readers and give them a wider view of Python.

As a thankyou, I would be glad to share your page with our 31k Facebook/Twitter/Linkedin Followers.
Or
I am happy to do Cross-Promotion.

Let me know your thoughts. Thanks.
Regards,
Vinay
PS: I am real a person... here is a number to contact me +1 302 308 5151


Counter: 39737 (from 2010/06/03), today: 10, yesterday: 0