MATLAB移民のためのJulia tips

MATLAB移民のためのJulia tips

何も考えずに速く計算できないのならば、何もやりたくない。

古いバージョン(v0.6あたり)のJuliaのtipsを見て「動かない!」となったときのtips (非網羅的)

Juliaがv1.0になってから、しばらく経ちました。もうv1.1も出ています。

この記事では、v0.6あたりからの差分を、気づいた分だけ列挙していこうと思います。(今更感がありますが、自分の作業ついでにまとめておきます。)

VoidNothingになりました。

以上です。

いくつかの関数は、読み込みが必要になりました。

  • sparseを使うときは、using SparseArrays
  • eigsなどはusing Arpack(Arpackが入れられない人は下部分参照)

次元指定は、dims=を付けます。

ERROR: LoadError: MethodError: objects of type Array{Float64,2} are not callable Use square brackets [] for indexing an Array.とかがエラーで出た人はこちら。

findminなどを使ったときに、 ERROR: LoadError: MethodError: no method matching findmin(::Array{Float64,2}, ::Int64)とか出て来た人もこちら。

x = rand(3,2)
sum(x,2) # v0.6
sum(x, dims=2) # >v0.7

sub2ind, ind2subがなくなりました。

CartesianIndicesLinearIndicesを使います。

無理やり変換:

function sub2ind((a,b),i,j)
    A = zeros(a,b)
    ind = LinearIndices(A)[i,j]
    return ind
end
function ind2sub((a,b), i)
    i2s = CartesianIndices(zeros(a,b))
    return i2s[i]
end

https://discourse.julialang.org/t/psa-replacement-of-ind2sub-sub2ind-in-julia-0-7/14666

eyeがなくなりました。

function eye(n)
    Diagonal{Float64}(I, n)
end

https://myenigma.hatenablog.com/entry/2018/08/12/113739

eigsなどはusing Arpackを読み込んでから使います。

https://discourse.julialang.org/t/replacement-of-eigs/13540

そしてこのArpack、Juliaをcondaから入れていた場合、失敗します... 本家のバイナリなら大丈夫ということです。 (add Arpackだけじゃなく、build Arpackも必要です...)

findfindallになりました。

以上です。

sortcols, sortrowssortslicesになりました。

オプションのby=x->(x[2],x[3])とかは、そのまま使えます。

こんなかんじ。

a = [1.0, 3.1, 3.2, 3.3]
b = [2.2, 2.4, 2.6, 2.8]
c = [3.9, 3.1, 1.3, 3.1]

m = transpose(hcat(a, b, c))

sortslices(m,dims=1,by=x->(x[2],x[3]))

PyPlotで行列のcolor plot

pcolormeshが一番簡単だと思ったのでメモ。

下のような3×3行列 prs をプロットする。

using PyPlot

prs = [1 2 3;4 5 6;7 8 9]

prsview = zeros(size(prs))
for k = 1:size(prs,1)
    prsview[k,:] = prs[size(prs,1)-k+1,:]
end

pcolormesh(prsview,cmap="Blues")
colorbar()
#savefig("Matrix.pdf")
  • そのままだと行と列の順番がアレなので、行だけひっくり返す。
  • 保存したい場合はsavefig

f:id:tatmann9:20171123120556p:plain
pcolormesh

JuliaでのPyPlot (matplotlib)

ぜんぜん網羅的ではありません。 自分で調べるたびに追加していきます。

種々のプロット

scatter plot

基本はこんなかんじ。

fig = figure("pyplot_scatterplot",figsize=(5,5))
ax = axes()

val1 = rand(10)
val2 = rand(10)
scatter(val1,val2,s=100,alpha=1,edgecolors="")
  • figsizeで図のサイズ指定。
  • ax = axes()は後でプロットを加工するときのためのおまじない。(たぶん)
  • sは点のサイズ、alpha(0~1)は透明度(1が不透明)。(pythonと同じ)
  • edgecolors=""は縁なしを意味。(pythonと違う)
  • (markerpythonと違うらしい。)

プロットの加工

aspect ratio

横幅を縦幅の2倍にするには

ax[:set_aspect](0.5)

figsizeでは、プロット全体の形を調整できるけれど、プロットの目盛は表示領域が歪んでいたりするので、これを使うと解決するときがある。

https://groups.google.com/forum/#!msg/julia-users/hyYoc7SkpU8/gYmc1bNyr8gJ

ファイル操作

一番基本的なことと、かゆいところだけ書きます。 全般的には、もっとちゃんと書いてある記事を参考にしてください。

ファイルの読み込み

open( "filename", "r" ) do fp
   for line in eachline( fp )
   ...
   end
end

もう少し具体的な例

N-by-2のテキストデータdata.txtを読み込んで、行列にしたい場合はこんなかんじ。

filename = "data.txt"
totalrows = countlines(open( filename, "r" ))
open( filename, "r" ) do fp
    cnt = 0
    dat = zeros(Int64,totalrows,2) # (ファイルの行数,2)のゼロ行列
    for line in eachline( fp ) # 行ごとに読み込む
    cnt += 1
        line = rstrip(line, '\n') # 改行消し。無くても大丈夫。
        u = split(line, " ") # スペース区切りで分割
        u1 = parse(Int64,u[1]) # 文字列を数値に変換
        u2 = parse(Int64,u[2])
        dat[cnt,1] = u1
        dat[cnt,2] = u2
    end
    println(dat) # 書き出してみる。
end

タブ区切りだったらsplit(line, "\t")

もっと詳しいことは、参考にさせていただいた、こちらのページをどうぞ。

Juliaでファイル操作 | mwSoft

ポインターを戻す

Pythonseek(0)。 Juliaでは、

seekstart(fp)

詳しくは

I/O and Network — Julia Language 0.5.1-pre documentation

ファイルへの書き込み

こんなかんじ。

fp = open("filename.txt","w")
write(fp, "Write something.\n")
close(fp)

条件を満たす行を行列から検索・抽出・削除

MATLABismember

例えば、

a = [1 2 3; 7 8 9]
B = [1 2 3;4 5 6;7 8 9;10 11 12]

行列Bのなかで、行列aの行と同じ要素を持っている行を検索・抽出・削除したい、というとき。

aが数の場合

行単位ではなく、Bの行列要素一つ一つを判定したい場合は、他の記事

julia.hatenablog.jp

でできる。 判定する要素が複数ある場合は、ここでの方法をマネしてやってみるとできるはず。

aがベクトルの場合

もし判定する行が1つだけの場合、例えば

a = [1 2 3]

のときは、

indices = Bool[ a == B[i,:] for i=1:size(B,1) ]

とすればマッチする行がtrue/falseで返ってくる。今の場合、{true, false, false, false} となる。

Bのなかでaと一致する行を削除したければ、

B[!indices,:]

# 4   5   6
# 7   8   9
# 10  11  12

aが行列の場合

一番上に挙げた例のように、判定する行が複数ある場合は、まずaを行ごとに区切られた多次元配列に分解:

as = [a[k,:] for k=1:size(a,1)]

ちなみにこれの中身はこんなかんじ:

# 2-element Array{Any,1}:
# 1x3 Array{Int64,2}:
# 1  2  3
# 1x3 Array{Int64,2}:
# 7  8  9

これを使って次のように判定:

indices = Bool[ B[i,:] in as for i=1:size(B,1) ]

Bのなかでaと一致する行を削除したければ、前節と同様に

B[!indices,:]

# 4   5   6
# 10  11  12

参考にさせていただいたもの:

Julia: find row in matrix - Stack Overflow