この記事について
この記事はJuliaのArray型を使ってみるというものです。
書き方について混乱をしたところがあるので書いてみようと思います。
今なお混乱してますが。
最後のまとめでは使用感と個人的な使用方法について書いております。
本編
Arrayの書き方色々(1次元)
JuliaでのArrayの書き方はいろいろあります。
# 基本的な形
julia> l1 = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> l2 = [1 2 3]
1×3 Array{Int64,2}:
1 2 3
すでに何か異なりますね。
「,」で区切るとベクトル的な値の持ち方ですが、「 」で区切ると1 * 3となり行列のような持ち方をしているように見えます。これは値の取得方法を見るとわかります。
# 値を取得
julia> l1[1]
1
julia> l1[1:2]
2-element Array{Int64,1}:
1
2
julia> l1[1,2]
ERROR: BoundsError: attempt to access 3-element Array{Int64,1} at index [1, 2]
Stacktrace:
[1] getindex(::Array{Int64,1}, ::Int64, ::Int64) at .\array.jl:732
[2] top-level scope at none:0
ベクトルであるl1の場合、[1,2]のように値を取得して来ようとするとエラーが出ます。
次にl2でどのようになるのかを見てみましょう
julia> l2[1]
1
julia> l2[1:2]
2-element Array{Int64,1}:
1
2
julia> l2[1,2]
2
julia> l2[1,1:2]
2-element Array{Int64,1}:
1
2
julia> l2[1,1:3]
3-element Array{Int64,1}:
1
2
3
julia> l2[1:1,1:3]
1×3 Array{Int64,2}:
1 2 3
どうやら取得する方法によっても行列として取得するのかベクトルとして出力するのかが選べるようです。
[1.1:3]のように取得するとベクトルですが、[1:1,1:3]で取得すると行列ですね。
Arrayの書き方色々(2次元)
とりあえずArrayの基本的な記述方法についてはわかりましたので、次に行こうと思います。
つまりは二次元配列の実装です。
では「,」区切りの場合を見てみます。先ほどではベクトルとして出力されてしまいましたが、二次元配列として入れるとどうなるのでしょうか。
「,(カンマ)」区切りの場合
julia> l1 = [[1,2,3],[4,5,6]]
2-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
あれ、Arrayの中にArrayが入ってしまいました。
でもまぁ行けるんじゃないかな?
julia> l1[1]
3-element Array{Int64,1}:
1
2
3
julia> l1[1:1]
1-element Array{Array{Int64,1},1}:
[1, 2, 3]
julia> l1[1:2]
2-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
julia> l1[1,2]
ERROR: BoundsError: attempt to access 2-element Array{Array{Int64,1},1} at index [1, 2]
Stacktrace:
[1] getindex(::Array{Array{Int64,1},1}, ::Int64, ::Int64) at .\array.jl:732
[2] top-level scope at none:0
julia> l1[1][2]
2
値の取得のされ方が「 」で区切ったデータと異なりますね。
少しモヤモヤしますがここはスルーして、よく使用する転置をしてみようと思います。
julia> l1
2-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
julia> l1'
1×2 LinearAlgebra.Adjoint{LinearAlgebra.Adjoint{Int64,Array{Int64,1}},Array{Array{Int64,1},1}}:
[1 2 3] [4 5 6]
なるほど、これはダメみたいですね。
Arrayの中にArrayが入ってしまっているので、外側のArrayだけが転置されてしまっているようです。
他にも試してみましょう
julia> l1 = [[1,2,3];[4,5,6]]
6-element Array{Int64,1}:
1
2
3
4
5
6
julia> l1 = [[1,2,3] [4,5,6]]
3×2 Array{Int64,2}:
1 4
2 5
3 6
l1 = [[1,2,3];[4,5,6]]はどう頑張っても二次元配列にはならなそうです。
l1 = [[1,2,3] [4,5,6]]なら転置したら行けそうですね
julia> rl = l1'
2×3 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
1 2 3
4 5 6
julia> rl
2×3 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
1 2 3
4 5 6
julia> rl[1,2]
2
julia> rl[1,1:3]
3-element Array{Int64,1}:
1
2
3
julia> rl[1:2,1:3]
2×3 Array{Int64,2}:
1 2 3
4 5 6
julia> rl[1:1,1:3]
1×3 Array{Int64,2}:
1 2 3
これなら二次元配列として使用することが出来ますね!
こんな面倒なことしたくありません。
「 (半角スペース)」区切りの場合
「,」で区切るととても使いにくいことがわかりました。
なので「 」で区切って楽に二次元配列を取得しましょう。
julia> l2 = [[1 2 3] [4 5 6]]
1×6 Array{Int64,2}:
1 2 3 4 5 6
くっついてしまいました。
julia> l2 = [[1 2 3],[4 5 6]]
2-element Array{Array{Int64,2},1}:
[1 2 3]
[4 5 6]
Arrayの中にArrayが入ってしまいました。
julia> l2 = [[1 2 3];[4 5 6]]
2×3 Array{Int64,2}:
1 2 3
4 5 6
ハイ出来ました!
これでできました!
何の問題もありませんでした!
julia> l2[1]
1
julia> l2[1:4]
4-element Array{Int64,1}:
1
4
2
5
julia> l2[1,1:3]
3-element Array{Int64,1}:
1
2
3
julia> l2[1:1,1:3]
1×3 Array{Int64,2}:
1 2 3
julia> l2[1:2,1:2]
2×2 Array{Int64,2}:
1 2
4 5
値もしっかりと取得することが出来ています。
l2[1:4]がちょっと不思議な動き方をしていますが気にしません!
困ったこと
二次元配列を作ろうとした際に、Pythonユーザーだったので[[1,2,3],[4,5,6]]と記述をしていました。その際に困ったのがDataFramesでのArrayの取り扱いです。
julia> df = DataFrame(l1)
3×2 DataFrame
│ Row │ x1 │ x2 │
│ │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1 │ 1 │ 4 │
│ 2 │ 2 │ 5 │
│ 3 │ 3 │ 6 │
julia> l2 = [[1 2 3];[4 5 6]]
2×3 Array{Int64,2}:
1 2 3
4 5 6
julia> df = DataFrame(l2)
2×3 DataFrame
│ Row │ x1 │ x2 │ x3 │
│ │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1 │ 1 │ 2 │ 3 │
│ 2 │ 4 │ 5 │ 6 │
l1を見ていただくとわかる通り、私の考えていたものと列と行が反対になって取り込まれてしまいました。
これなら転置すればいいだろうと思ったのですが、
julia> df = DataFrame(l1')
1×2 DataFrame
│ Row │ x1 │ x2 │
│ │ LinearAl… │ LinearAl… │
├─────┼───────────┼───────────┤
│ 1 │ [1 2 3] │ [4 5 6] │
こうなりました。
まとめ
Arrayを簡単に触ってみたまとめです。
「,」区切りと「 」区切りの違いはなんとなく分かった気がします。
- 配列ならば「,」を使用する
- 行列ならば「 」を使用する
- Juliaは配列と行列を明確に分けている?
- 「,」を使用して多次元配列を作成することもできるが、データの取得方法が異なるので気を付けること(プロジェクト内で使用方法を統一する)
- パッケージにArrayを送り付ける際にはどのようにデータが取り扱われているのかを調べること
- 以下のような使い方もできるので「,」区切りをするなとは言えない
julia> l3 = [[1,2,[3,4,5]],[6,7,[8,9,10]]]
2-element Array{Array{Any,1},1}:
[1, 2, [3, 4, 5]]
[6, 7, [8, 9, 10]]
julia> l3[1]
3-element Array{Any,1}:
1
2
[3, 4, 5]
julia> l3[1][2]
2
julia> l3[1][3]
3-element Array{Int64,1}:
3
4
5
julia> l3[1][3][1]
3
画像とかの処理で使えそう?
「 」でこれを作ろうとすると2*5Arrayが作成されます。
おまけというか答えというか
Juliaのプログラム上でどのように扱われるのかを調べてみました
function ArrayCheck(l::AbstractVector)
println("vector")
end
function ArrayCheck(l::AbstractMatrix)
println("Matrix")
end
l1 = [1,2,3]
l2 = [[1,2,3],[4,5,6]]
l3 = [1 2 3]
ArrayCheck(l1)
ArrayCheck(l2)
ArrayCheck(l3)
vector
vector
Matrix
最後に
JuliaでのArrayで面白い話がありましたら教えてください。
また、本記事の中で間違えている点がございましたら、ご指摘ください。
よろしくお願いいたします。