『機械学習のエッセンス(http://isbn.sbcr.jp/93965/)』のPythonサンプルをJuliaで書き換えてみる。（第04章02NumPyの基本）

# はじめに

[『機械学習のエッセンス(http://isbn.sbcr.jp/93965/)』のPythonサンプルをJuliaで書き換えてみる。（第04章01数値計算の基本）](https://qiita.com/yshutaro/items/daa1fcfdac31140e8fae)の続きです。

※本との対比のため同じ見出しを付けていますが、NumPyではなくJuliaで書いているので以下の見出しからはNumPyは削除しています。

## 関数

+ eのべき乗
+ 自然対数
+ 正弦
+ 平方根

```julia
julia> exp(2)
7.38905609893065

julia> log(ℯ)
1

julia> sin(π)
1.2246467991473532e-16

julia> sqrt(3)
1.7320508075688772
```

Juliaは「π」とか「ℯ」がそのまま使えるのが面白いですね。
日本語IMEだと「π」は”ぱい（pai）”と打って変換できますが、「ℯ」はいろいろ試したのですが変換できず、調べたらREPL上で`\euler`と打って、Tabキーを押して変換できるようです。
上記の`log(ℯ)`は
`log(\euler`
まで打ってここでTabキーを押すと
`log(ℯ`
となりました。`π`は`\pi`ですね。

# 配列

Juliaの配列のインデックスは「1」始まりなので、インデックス指定をするときPythonとは番号が異なります。なるべく本の結果と同じになるようにインデックスを調整しました。

```julia
julia> a = [2, 3, 5, 7, 8]
5-element Array{Int64,1}:
 2
 3
 5
 7
 8
```

+ 先頭の要素

```julia
julia> a[1]
2
```

+ インデックス2〜3の要素

```julia

julia> a[2:3]
2-element Array{Int64,1}:
 3
 5
```

+ インデックス3〜5-1=4までの要素

```julia
julia> a[3:-1]
0-element Array{Int64,1}

julia> a[3:end-1]
2-element Array{Int64,1}:
 5
 7
```

Juliaはインデックス「-1」は最後から−１の要素にならなく、`end`が最後のインデックスなので`end-1`となります。

+ range指定の配列の作成。Juliaでは`collect`関数を使う。

```julia
julia> b = collect(0:4)
5-element Array{Int64,1}:
 0
 1
 2
 3
 4
```

+ ステップを`0.2`にする。

これも`collect`を使います。Pythonと違ってSTEPを真ん中に書くとうまくいきました。

```julia
julia> c = collect(1:0.2:3)
11-element Array{Float64,1}:
 1.0
 1.2
 1.4
 1.6
 1.8
 2.0
 2.2
 2.4
 2.6
 2.8
 3.0
```

ただし、3まで指定すると最後の3自身が入るようです（Pythonの例では2.8まで）。同じ結果にするには`collect(1:0.2:2.8)`でしょうか。未満の書き方があるかはわかりませんでした。

+ 型の確認

```julia
julia> typeof(a)
Array{Int64,1}

julia> typeof(c)
Array{Float64,1}
```

+ 作成時に型を指定する。

```julia
julia> d = Float64[1, 2, 3]
3-element Array{Float64,1}:
 1.0
 2.0
 3.0

julia> typeof(d)
Array{Float64,1}
```

+ 引数に浮動小数点数を指定

```julia
julia> e = collect(0.:4.)
5-element Array{Float64,1}:
 0.0
 1.0
 2.0
 3.0
 4.0

julia> typeof(e)
Array{Float64,1}
```

# 2次元配列

## 2次元配列の操作

```julia
julia> a = Float64[2 3 4; 5 6 7]
2×3 Array{Float64,2}:
 2.0  3.0  4.0
 5.0  6.0  7.0
```

+ 第1行・第2列の要素
+ 第2列の全ての要素
+ 第2行の全ての要素
+ 第1行の第3列以降
+ 第1行の3列より前

```julia
julia> a[1, 2]
3.0

julia> a[:, 2]
2-element Array{Float64,1}:
 3.0
 6.0

julia> a[2, :]
3-element Array{Float64,1}:
 5.0
 6.0
 7.0

julia> a[1, 3:end]
1-element Array{Float64,1}:
 4.0

julia> a[1, 1:2]
2-element Array{Float64,1}:
 2.0
 3.0
```

最後の「第1行の3列より前」の書き方はわからず、インデックスの範囲指定にしました。

# 配列のデータ属性

+ 3行5列の2次元配列に変換

```julia
julia> a = reshape(collect(0.:14.), 3, 5)
3×5 Array{Float64,2}:
 0.0  3.0  6.0   9.0  12.0
 1.0  4.0  7.0  10.0  13.0
 2.0  5.0  8.0  11.0  14.0
```

※Pythonの行列表示とは転置状態になっています。

+ 配列の形状

Pythonの`shape`にあたる関数は`size`でいけました。

```julia
julia> size(a)
(3, 5)
```

+ 配列の次元数
+ 要素数。これは`size`でなく`length`でした。

```julia
julia> ndims(a)
2

julia> length(a)
15
```

+ 1次元配列のまま

```julia
julia> b = collect(0.:3.)
4-element Array{Float64,1}:
 0.0
 1.0
 2.0
 3.0

julia> size(b)
(4,)

julia> ndims(b)
1

julia> length(b)
4
```

# reshape関数と形状の変更

※本ではreshapeメソッドとなっていますが、Juliaでは関数の方があっていそうなので見出しは変更しました。

## 形状のいろいろな変更方法

```julia
julia> a = collect(0.:15.)
16-element Array{Float64,1}:
  0.0
  1.0
  2.0
  3.0
  4.0
  5.0
  6.0
  7.0
  8.0
  9.0
 10.0
 11.0
 12.0
 13.0
 14.0
 15.0
```

+ 列数自動で形状の変更

```julia
julia> c = reshape(a, 4, :)
4×4 Array{Float64,2}:
 0.0  4.0   8.0  12.0
 1.0  5.0   9.0  13.0
 2.0  6.0  10.0  14.0
 3.0  7.0  11.0  15.0
```

+ 1次元配列に戻す

```julia
julia> vec(c)
16-element Array{Float64,1}:
  0.0
  1.0
  2.0
  3.0
  4.0
  5.0
  6.0
  7.0
  8.0
  9.0
 10.0
 11.0
 12.0
 13.0
 14.0
 15.0
```

+ 行数自動で形状の変更
+ 列数自動で形状の変更

```julia
julia> b = collect(0.:3.)
4-element Array{Float64,1}:
 0.0
 1.0
 2.0
 3.0

julia> reshape(b, :, 1)
4×1 Array{Float64,2}:
 0.0
 1.0
 2.0
 3.0

julia> reshape(b, 1, :)
1×4 Array{Float64,2}:
 0.0  1.0  2.0  3.0
```

Juliaで`np.newaxis`にあたるものはわかりませんでした。

# その他の配列の操作

## いろいろな配列の作成

+ 要素が全て0である配列の作成

```julia
julia> a = zeros(3, 4)
3×4 Array{Float64,2}:
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
```

+ 要素が全て1である配列の作成

```julia
julia> b = ones(2, 2)
2×2 Array{Float64,2}:
 1.0  1.0
 1.0  1.0
```

+ 任意の要素を持つ配列の作成

~~`np.empty`にあたるJuliaの関数は見当たらず・・・。~~
@tenfu2tea さんにご教示いただきました！
`np.empty`にあたるJuliaの関数は`Base.similar(Storagetype, axes)` ということです。
https://docs.julialang.org/en/v1.0/base/arrays/#Base.similar

マニュアル読みましたが引数の指定が難しいですね・・・。`similar`なので似ているものを作ると言うことでしょうか。
本に近い形で作ろうとして下記のようになりました。

```julia
julia> similar(1:10, Float64, 2, 5)
2×5 Array{Float64,2}:
 2.21031e-314  4.94066e-324  2.21031e-314  4.94066e-323  2.47033e-323
 2.21031e-314  2.21031e-314  2.21031e-314  5.92879e-323  2.19521e-314
```

+ 等差数列を要素として持つ配列の作成

~~`linspace`はないみたいなので、~~ `range`で指定するようです。
こちらも、@tenfu2tea さんにご教示いただきました！
`LinRange`で指定するとのことです。
https://docs.julialang.org/en/v1.0/base/collections/#Base.LinRange

`range`で指定した方法と`LinRange`で指定した方法を載せておきます。

+ range

```julia
julia> collect(range(0., stop = 1., length = 10))
10-element Array{Float64,1}:
 0.0               
 0.1111111111111111
 0.2222222222222222
 0.3333333333333333
 0.4444444444444444
 0.5555555555555556
 0.6666666666666666
 0.7777777777777778
 0.8888888888888888
 1.0 
```

+ LinRange

```julia
julia> collect(LinRange(0., 1., 10))
10-element Array{Float64,1}:
 0.0
 0.1111111111111111
 0.2222222222222222
 0.3333333333333333
 0.4444444444444444
 0.5555555555555556
 0.6666666666666666
 0.7777777777777778
 0.8888888888888888
 1.0
```

# 行列の連結

## いろいろな行列の連結

+ 2次元配列を2つ用意

```julia
julia> a = [0 1 2; 3 4 5]
2×3 Array{Int64,2}:
 0  1  2
 3  4  5

julia> b = [6 7 8; 9 10 11]
2×3 Array{Int64,2}:
 6   7   8
 9  10  11
```

+ 縦方向に連結

```julia
julia> vcat(a, b)
4×3 Array{Int64,2}:
 0   1   2
 3   4   5
 6   7   8
 9  10  11
```

+ 横方向に連結

```julia
julia> hcat(a, b)
2×6 Array{Int64,2}:
 0  1  2  6   7   8
 3  4  5  9  10  11
```

+ さらに1次元配列を2つ用意

```julia
julia> c = collect(0:2)
3-element Array{Int64,1}:
 0
 1
 2

julia> d = collect(3:5)
3-element Array{Int64,1}:
 3
 4
 5
```

+ 縦方向に連結と横方向に連結

```julia
julia> vcat(c, d)
6-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5

julia> hcat(c, d)
3×2 Array{Int64,2}:
 0  3
 1  4
 2  5
```

+ 形状が合わないとエラー

```julia
julia> vcat(a, c)
ERROR: ArgumentError: number of columns of each array must match (got (3, 1))
Stacktrace:
 [1] _typed_vcat(::Type{Int64}, ::Tuple{Array{Int64,2},Array{Int64,1}}) at ./abstractarray.jl:1283
 [2] typed_vcat at ./abstractarray.jl:1297 [inlined]
 [3] vcat(::Array{Int64,2}, ::Array{Int64,1}) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/SparseArrays/src/sparsevector.jl:1065
 [4] top-level scope at none:0
```

+ 2次元配列に変換してから連結

```julia
julia> vcat(a, reshape(c, 1, :))
3×3 Array{Int64,2}:
 0  1  2
 3  4  5
 0  1  2
```