Julia で統計解析 第 9 章 関数¶

In [1]:
Version()
最新バージョン 2024-07-18 11:16

統計解析を行う上で,ファイルからデータフレームに読み込んだ変数をそのまま使うということは意外と少ない。データフレームの変数を変換したり,新たな変数を作成したりという作業が必要である。そのような場合に,四則演算などの演算子や平方根を取る関数 sqrt() や対数を取る関数 log() などの基本的数学関数以外にも様々な関数がある。

データの種類¶

定数¶

数学定数¶

  • 円周率は REPL 環境では \ p i tabキー で入力できる。
In [2]:
π
Out[2]:
π = 3.1415926535897...

1π は数学的には π と同じであるが,Julia では 1π は倍精度実数(Float64)であり,単に π と書いたときとは表示が異なる。

In [3]:
1π
Out[3]:
3.141592653589793
In [4]:
typeof(1π)
Out[4]:
Float64

π の型は Irrational{:π} である。

In [5]:
typeof(π)
Out[5]:
Irrational{:π}

Julia には,任意の精度の浮動小数点型 BigFloat がある。デフォルトでは 256 ビット実数なので,有効桁数はほぼ 77 桁である(実際には 79 桁が表示されるが)。

これを用いて π を型変換して表示してみると,以下のようになる。

In [6]:
BigFloat(π)
Out[6]:
3.141592653589793238462643383279502884197169399375105820974944592307816406286198

1000 ビット実数に設定すると,有効桁数が 1000*log10(2)≒301 桁になる(実際には 302 桁が表示される)。

In [7]:
setprecision(BigFloat, 1000) # 精度を 1000 ビットにする。
BigFloat(π)
Out[7]:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412736

π の入力が面倒だと言う人は,pi と書いても同じである。

In [8]:
pi # π と同じ
Out[8]:
π = 3.1415926535897...
  • ネイピア数は REPL 環境では \ e u l e r tabキー で入力できる。
In [9]:
ℯ
Out[9]:
ℯ = 2.7182818284590...
In [10]:
typeof(ℯ)
Out[10]:
Irrational{:ℯ}

円周率と同じで,ℯ の型は Irrational{:ℯ} である。

自分で定義する定数¶

定数はプログラム中で一定不変の値を持つものとして定義できる。普通の変数なら間違えて変更してしまうことがあるが,定数は変更すると警告が出る。警告は出るが,実行はされるので注意が必要である。

このようなことから,定数は大文字で指定するのが慣例である。

In [11]:
const YEAR = 2020
YEAR += 1 # 実行されるが,警告が出る
YEAR
WARNING: redefinition of constant Main.YEAR. This may fail, cause incorrect answers, or produce other errors.
Out[11]:
2021

数¶

整数¶

整数の型は数種類ある。

もっとも一般的に使われるのが Int64 で,-9223372036854775808 から 9223372036854775807 の整数を表すことができるので,大概の用に間に合う。

もっと広い範囲の値を扱う必要がある場合には Int128, BigInt が使える。

In [12]:
(2, typeof(2))
Out[12]:
(2, Int64)
In [13]:
typeof(12345678900000000000000)
Out[13]:
Int128
In [14]:
typeof(123456789000000000000000000000000000000000000000000)
Out[14]:
BigInt

■ 整数の型と値の範囲

In [15]:
for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128]
    println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]")
end
   Int8: [-128,127]
  Int16: [-32768,32767]
  Int32: [-2147483648,2147483647]
  Int64: [-9223372036854775808,9223372036854775807]
 Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
  UInt8: [0,255]
 UInt16: [0,65535]
 UInt32: [0,4294967295]
 UInt64: [0,18446744073709551615]
UInt128: [0,340282366920938463463374607431768211455]

実数(浮動小数点数)¶

実数は Float64 型が一般的に使われる。

In [16]:
(2.0, typeof(2.0))
Out[16]:
(2.0, Float64)

64 ビット実数とも呼ばれるが,数を表すのには 64 ビットのうちの 52 ビットが仮数部として使われる。細かいことをいえば,52 ビットの上に暗黙の 1 ビットがあると仮定するので,有効桁数は 53*log10(2)≒15.9546 で,実質 16 桁と思っておけばよい。

In [17]:
4503599627370496.0, 4503599627370497.0, 9007199254740991.0, 9007199254740992.0 # 正確に表現できる最大数
Out[17]:
(4.503599627370496e15, 4.503599627370497e15, 9.007199254740991e15, 9.007199254740992e15)
In [18]:
4503599627370496.0, 4503599627370496.1, 4503599627370496.2, 4503599627370496.3 # 区別できない
Out[18]:
(4.503599627370496e15, 4.503599627370496e15, 4.503599627370496e15, 4.503599627370496e15)

最小の精度は 1/(2^52)≒2.220446049250313e-16 で,この値のことを Machine epsilon という。2つの実数の差がこの値より大きければ,2つの実数として扱われることになる。

In [19]:
2^-52, eps(1.0), eps(Float64) # Machine epsilon
Out[19]:
(2.220446049250313e-16, 2.220446049250313e-16, 2.220446049250313e-16)

いろいろ細かいことはあるが,2 進数ベースのコンピュータで扱える浮動小数点数は,近似値であるということを肝に銘じておくことが肝心だ。

64 ビットのうちの残り 11 ビットは バイアスのある指数部(符号なし整数)と 1 ビットの符号である。

これらを併せて $\text{符号}\times\text{仮数部}\times2^{\text{指数部−1023}}$ で数を表す。

より詳しくは,Wikipedia の倍精度浮動小数点数 を参照する。

Float64 は Inf,-Inf,NaN, missing という特別な値を持つことができる。

In [20]:
Inf, -Inf, NaN, missing
Out[20]:
(Inf, -Inf, NaN, missing)

これらは,相互の演算において厄介な振る舞いを見せるので注意が必要である。

In [21]:
NaN == NaN, isnan(NaN)
Out[21]:
(false, true)
In [22]:
missing == missing, ismissing(missing)
Out[22]:
(missing, true)
In [23]:
NaN ==  missing
Out[23]:
missing
In [24]:
3 + NaN, 4 * missing
Out[24]:
(NaN, missing)

虚数¶

  • 定数

虚数の記述法は言語によって異なる。Julia では実部 ± 虚部im である。

In [25]:
7 + 2im, typeof(7 + 2im)
Out[25]:
(7 + 2im, Complex{Int64})
In [26]:
7.1 + 2.2im, typeof(7.1 + 2.2im)
Out[26]:
(7.1 + 2.2im, ComplexF64)
  • complex(x) 実部が x の複素数を作る。
In [27]:
x = 1.2
complex(x)
Out[27]:
1.2 + 0.0im
  • complex(x) 実部が x,虚部が y の複素数を作る。
In [28]:
x = 1.2; y = 3.6
complex(x, y) # x + y im などと書くことはできない
Out[28]:
1.2 + 3.6im
  • 複素数 z の実部を返す。
In [29]:
z = 7.1 + 2.2im
real(z)
Out[29]:
7.1
  • 複素数 z の虚部を返す。
In [30]:
imag(z)
Out[30]:
2.2
  • 複素数 z の共役複素数を返す。
In [31]:
conj(z)
Out[31]:
7.1 - 2.2im
  • 複素数 z の絶対値を返す。abs(z) ≡ sqrt(real(z)^2 + imag(z)^2)
In [32]:
abs(z)
Out[32]:
7.433034373659252
  • 複素数 z の絶対値の 2 乗を返す。abs(z) ≡ real(z)^2 + imag(z)^2
In [33]:
abs2(z)
Out[33]:
55.25
  • 複素数 z の偏角 ∠z をラジアンで返す。結果(値域)は −π から π である。
In [34]:
z = complex(-1/2, sqrt(3)/2)
angle(z)
Out[34]:
2.0943951023931957

タプル¶

タプルは複数の要素をカンマで区切り,全体を ( ) で囲んだものである。

空のタプル¶

In [35]:
t = ()
Out[35]:
()

タプルを定義する¶

In [36]:
t = (1, 2, 3)
typeof(t)
Out[36]:
Tuple{Int64, Int64, Int64}

要素は様々な型が混在していてかまわない。

In [37]:
nt = (a = 1, b = "foo", c = 3.14, d = 'x')
nt |> println
(a = 1, b = "foo", c = 3.14, d = 'x')

なお,要素が 1 個の場合には要素の後に , が必要である。

In [38]:
(24,)
Out[38]:
(24,)

タプルの要素の参照¶

要素は様々な方法で参照できる。

In [39]:
nt[1]
Out[39]:
1
In [40]:
nt.b
Out[40]:
"foo"
In [41]:
nt[:c]
Out[41]:
3.14

ただし,代入はできない(イミュータブルと言われる)。

In [42]:
# nt[2] = 5   MethodError になる

タプルを対象とする関数¶

In [43]:
keys(nt) # キーのリスト
Out[43]:
(:a, :b, :c, :d)
In [44]:
values(nt) # 値のリスト
Out[44]:
(1, "foo", 3.14, 'x')
In [45]:
isempty(nt) # 空か?
Out[45]:
false
In [46]:
length(nt) # 長さ(要素数)
Out[46]:
4

ベクトル¶

空ベクトル¶

空ベクトルは [] で定義できるが,型が決められるならば型を指定する。

In [47]:
[], Int[], Float64[], String[], Char[]
Out[47]:
(Any[], Int64[], Float64[], String[], Char[])

行ベクトル¶

実は 1×n 行列である。空白で要素を区切り [ ] で囲む。

In [48]:
[1 2 3 4 5]
Out[48]:
1×5 Matrix{Int64}:
 1  2  3  4  5

列ベクトル¶

カンマまたはセミコロンで要素を区切り [ ] で囲む。

In [49]:
[2, 4, 6]
Out[49]:
3-element Vector{Int64}:
 2
 4
 6
In [50]:
[2; 4; 6]
Out[50]:
3-element Vector{Int64}:
 2
 4
 6

ベクトルの要素は任意の型が混在していてかまわない。それぞれの要素を , で区切って全体を [ ] で囲む。

In [51]:
[1, 2.0, "abc", 'x'] |> println
Any[1, 2.0, "abc", 'x']

整数ゼロベクトル¶

In [52]:
repeat([0], 3) |> println
[0, 0, 0]
In [53]:
fill(0, 3) |> println
[0, 0, 0]
In [54]:
zeros(Int, 3) |> println
[0, 0, 0]

実数ゼロベクトル¶

In [55]:
repeat([0.0], 3) |> println
[0.0, 0.0, 0.0]
In [56]:
fill(0.0, 3) |> println
[0.0, 0.0, 0.0]
In [57]:
zeros(3) |> println
[0.0, 0.0, 0.0]

整数 1 ベクトル¶

In [58]:
repeat([1], 3) |> println
[1, 1, 1]
In [59]:
fill(1, 3) |> println
[1, 1, 1]
In [60]:
ones(Int, 3) |> println
[1, 1, 1]

実数 1 ベクトル¶

In [61]:
repeat([1.0], 3) |> println
[1.0, 1.0, 1.0]
In [62]:
fill(1.0, 3) |> println
[1.0, 1.0, 1.0]
In [63]:
ones(3) |> println
[1.0, 1.0, 1.0]

論理 trues ベクトル¶

In [64]:
trues(5) |> println
Bool[1, 1, 1, 1, 1]
In [65]:
fill(true, 5) |> println
Bool[1, 1, 1, 1, 1]

論理 falses ベクトル¶

In [66]:
falses(5) |> println
Bool[0, 0, 0, 0, 0]
In [67]:
fill(false, 5) |> println
Bool[0, 0, 0, 0, 0]

等差ベクトル¶

初項 $a$,公差 $b$,最終項 $c$ の等差ベクトル collect(a:b:c)

In [68]:
Vector(1:5) |> println
[1, 2, 3, 4, 5]
In [69]:
collect(1:5) |> println
[1, 2, 3, 4, 5]
In [70]:
[1:5;] |> println
[1, 2, 3, 4, 5]
In [71]:
[1:5] |> println
UnitRange{Int64}[1:5]
In [72]:
(1:5) |> println
1:5
In [73]:
collect(10:1:15) |> println
[10, 11, 12, 13, 14, 15]
In [74]:
collect(1:2:10) |> println
[1, 3, 5, 7, 9]
In [75]:
collect(8:-2:0) |> println
[8, 6, 4, 2, 0]
In [76]:
collect(0:0.1:0.5) |> println
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]

初項 $a$ ,公差 $b$ ,項数 $n$ の等差ベクトル

In [77]:
a, b, n = 25, 5, 10
collect(range(a, step=b, length=n)) |> println
[25, 30, 35, 40, 45, 50, 55, 60, 65, 70]

等比ベクトル¶

初項 $a$,公比 $b$,項数 $n$ の等比ベクトル

In [78]:
a, b, n = 1, 1.1, 5
a .* b .^ collect(1:n) |> println
[1.1, 1.2100000000000002, 1.3310000000000004, 1.4641000000000004, 1.6105100000000006]

要素の参照¶

要素の参照は,1 〜 length(x) の値を取る添字式で行う。なお,length(x) を end で表すことができる。

In [79]:
x = collect(1:10)
x[1], x[end], x[end-2] # 先頭,末尾,末尾の 2 つ前を参照する
Out[79]:
(1, 10, 8)
In [80]:
x[iseven.(x)] |> println # true に対応する要素を参照する
[2, 4, 6, 8, 10]
In [81]:
x[1:2:10] |> println # 1 から 2 刻みで 10 までを参照する
[1, 3, 5, 7, 9]
In [82]:
x[3:8] |> println # 3 から 8 までを参照する
[3, 4, 5, 6, 7, 8]

ベクトルを対象とする関数¶

In [83]:
a = [1, 2, 3]
length(a) # 長さ
Out[83]:
3
In [84]:
isempty(a) # 空か?
Out[84]:
false
In [85]:
empty!(a) # 空にする
Out[85]:
Int64[]
In [86]:
a = [1, 2, 3]
pushfirst!(a, 0) |> println # 先頭に要素を追加する
[0, 1, 2, 3]
In [87]:
a = [1, 2, 3]
x = popfirst!(a) # 先頭の要素を取り出す
x |> println
a |> println
1
[2, 3]
In [88]:
a = [1, 2, 3]
push!(a, 99) |> println # 先頭の要素を取り出す
[1, 2, 3, 99]
In [89]:
a = [1, 2, 3]
pop!(a) |> println # 先頭の要素を取り出す
a |> println
3
[1, 2]
In [90]:
a = [1, 2, 3]
popat!(a, 2) # 先頭の要素を取り出す
a |> println
[1, 3]
In [91]:
a = [1, 2, 3]
insert!(a, 2, 44) # 先頭の要素を取り出す
a |> println
[1, 44, 2, 3]
In [92]:
a = [1, 2, 3]
deleteat!(a, 3) # 先頭の要素を取り出す
a |> println
[1, 2]
In [93]:
a = [1,2,3]
b = [10,20,30]
[a; b] |> println # ベクトルの後ろにベクトルを連結する
[1, 2, 3, 10, 20, 30]
In [94]:
vcat(a, b) |> println # ベクトルの後ろにベクトルを連結する
[1, 2, 3, 10, 20, 30]
In [95]:
cat(a, b, dims=1) |> println # ベクトルの後ろにベクトルを連結する
[1, 2, 3, 10, 20, 30]
In [96]:
hcat(a, b) # 縦ベクトルを横方向に連結する
Out[96]:
3×2 Matrix{Int64}:
 1  10
 2  20
 3  30
In [97]:
cat(a, b, dims=2) # 縦ベクトルを横方向に連結する
Out[97]:
3×2 Matrix{Int64}:
 1  10
 2  20
 3  30

cat() で長さの異なるベクトルを dims=2 で連結すると 1 × n 行列になる

In [98]:
x = [1 2 3]
y = [4 5 6 7]
cat(x, y, dims=2) #
Out[98]:
1×7 Matrix{Int64}:
 1  2  3  4  5  6  7
In [99]:
vec1 = collect(1:6) # ベクトル
vec1 |> println
reshape(vec1, 2, 3) # 2 × 3 行列に変換
[1, 2, 3, 4, 5, 6]
Out[99]:
2×3 Matrix{Int64}:
 1  3  5
 2  4  6
In [100]:
reshape(vec1, (2, 3)) # 次元をタプルで指定してもよい
Out[100]:
2×3 Matrix{Int64}:
 1  3  5
 2  4  6
In [101]:
reshape(vec1, 2, :) # `:` の次元は自動的に計算される
Out[101]:
2×3 Matrix{Int64}:
 1  3  5
 2  4  6
In [102]:
reshape(vec1, 6, :) # 6 × 1 行列
Out[102]:
6×1 Matrix{Int64}:
 1
 2
 3
 4
 5
 6

行列¶

整数ゼロ行列¶

In [103]:
zeros(Int, 2, 3)
Out[103]:
2×3 Matrix{Int64}:
 0  0  0
 0  0  0
In [104]:
fill(0, 2, 3)
Out[104]:
2×3 Matrix{Int64}:
 0  0  0
 0  0  0

実数ゼロ行列¶

In [105]:
zeros(2, 3)
Out[105]:
2×3 Matrix{Float64}:
 0.0  0.0  0.0
 0.0  0.0  0.0
In [106]:
fill(0.0, 2, 3)
Out[106]:
2×3 Matrix{Float64}:
 0.0  0.0  0.0
 0.0  0.0  0.0

整数 1 行列¶

In [107]:
ones(Int, 2, 3)
Out[107]:
2×3 Matrix{Int64}:
 1  1  1
 1  1  1
In [108]:
fill(1, 2, 3)
Out[108]:
2×3 Matrix{Int64}:
 1  1  1
 1  1  1

実数 1 行列¶

In [109]:
ones(2, 3)
Out[109]:
2×3 Matrix{Float64}:
 1.0  1.0  1.0
 1.0  1.0  1.0
In [110]:
fill(1.0, 2, 3)
Out[110]:
2×3 Matrix{Float64}:
 1.0  1.0  1.0
 1.0  1.0  1.0

論理 trues 行列¶

In [111]:
trues(2, 3)
Out[111]:
2×3 BitMatrix:
 1  1  1
 1  1  1
In [112]:
fill(true, 2, 3)
Out[112]:
2×3 Matrix{Bool}:
 1  1  1
 1  1  1

論理 falses 行列¶

In [113]:
falses(2, 3)
Out[113]:
2×3 BitMatrix:
 0  0  0
 0  0  0
In [114]:
fill(false, 2, 3)
Out[114]:
2×3 Matrix{Bool}:
 0  0  0
 0  0  0

単位行列¶

In [115]:
using LinearAlgebra
Array{Int}(I, 3, 3)
Out[115]:
3×3 Matrix{Int64}:
 1  0  0
 0  1  0
 0  0  1
In [116]:
Array{Int}(I, 2, 3)
Out[116]:
2×3 Matrix{Int64}:
 1  0  0
 0  1  0
In [117]:
Array{Float64}(I, 3, 3)
Out[117]:
3×3 Matrix{Float64}:
 1.0  0.0  0.0
 0.0  1.0  0.0
 0.0  0.0  1.0
In [118]:
Array{Bool}(I, 3, 3)
Out[118]:
3×3 Matrix{Bool}:
 1  0  0
 0  1  0
 0  0  1

対角行列¶

In [119]:
diagm(0 => 1:3)
Out[119]:
3×3 Matrix{Int64}:
 1  0  0
 0  2  0
 0  0  3
In [120]:
Diagonal([1,2,3])
Out[120]:
3×3 Diagonal{Int64, Vector{Int64}}:
 1  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  3

対角要素の n 上

In [121]:
diagm(1 => 1:3)
Out[121]:
4×4 Matrix{Int64}:
 0  1  0  0
 0  0  2  0
 0  0  0  3
 0  0  0  0

対角要素の n 下

In [122]:
diagm(-2 => 1:3)
Out[122]:
5×5 Matrix{Int64}:
 0  0  0  0  0
 0  0  0  0  0
 1  0  0  0  0
 0  2  0  0  0
 0  0  3  0  0

複数指定可能

In [123]:
diagm(-1 => 1:3, 1 => [10, 20, 30, 40])
Out[123]:
5×5 Matrix{Int64}:
 0  10   0   0   0
 1   0  20   0   0
 0   2   0  30   0
 0   0   3   0  40
 0   0   0   0   0

行列を対象とする関数¶

In [124]:
a = zeros(10, 5);
size(a), size(a, 1), size(a, 2) # 行列のサイズ
Out[124]:
((10, 5), 10, 5)
In [125]:
length(a) # 行列の要素数
Out[125]:
50
In [126]:
ndims(a) # 行列の次元数
Out[126]:
2
In [127]:
using LinearAlgebra
a = [1 2 3; 4 5 6; 7 8 9]
Base.print_matrix(stdout, a, "", " ", "\n\n")
diag(a) |> println # 対角要素の取り出し
1 2 3
4 5 6
7 8 9

[1, 5, 9]
In [128]:
diag(a, 1) |> println # 対角要素より n 上
[2, 6]
In [129]:
diag(a, -1) |> println # 対角要素より n 下
[4, 8]
In [130]:
tr(a), sum(diag(a)) # トレース(対角成分の和)
Out[130]:
(15, 15)
In [131]:
a[triu(trues(size(a)))] |> println # 上三角要素の取り出し
[1, 2, 5, 3, 6, 9]
In [132]:
a[triu(trues(size(a)), 1)] |> println
[2, 3, 6]
In [133]:
UpperTriangular(a)
Out[133]:
3×3 UpperTriangular{Int64, Matrix{Int64}}:
 1  2  3
 ⋅  5  6
 ⋅  ⋅  9
In [134]:
a[tril(trues(size(a)))] |> println # 下三角要素の取り出し
[1, 4, 7, 5, 8, 9]
In [135]:
a[tril(trues(size(a)), -2)] |> println
[7]
In [136]:
LowerTriangular(a)
Out[136]:
3×3 LowerTriangular{Int64, Matrix{Int64}}:
 1  ⋅  ⋅
 4  5  ⋅
 7  8  9
In [137]:
transpose(a) # 転置
Out[137]:
3×3 transpose(::Matrix{Int64}) with eltype Int64:
 1  4  7
 2  5  8
 3  6  9
In [138]:
a' # 転置
Out[138]:
3×3 adjoint(::Matrix{Int64}) with eltype Int64:
 1  4  7
 2  5  8
 3  6  9
In [139]:
rotr90(a) # 90度右回転
Out[139]:
3×3 Matrix{Int64}:
 7  4  1
 8  5  2
 9  6  3
In [140]:
rotl90(a) # 90度左回転
Out[140]:
3×3 Matrix{Int64}:
 3  6  9
 2  5  8
 1  4  7
In [141]:
rotl90(rotl90(a)) # 90度左回転,90度左回転 == rotl90(a, 2)
Out[141]:
3×3 Matrix{Int64}:
 9  8  7
 6  5  4
 3  2  1
In [142]:
rotl90(rotl90(rotl90(a))) # 90度左回転,90度左回転,90度左回転  == rotl90(a, 3)
Out[142]:
3×3 Matrix{Int64}:
 7  4  1
 8  5  2
 9  6  3
In [143]:
rotl90(rotl90(rotl90(rotl90(a)))) # 90度左回転,90度左回転,90度左回転,90度左回転
Out[143]:
3×3 Matrix{Int64}:
 1  2  3
 4  5  6
 7  8  9
In [144]:
rot180(a) # 180度回転
Out[144]:
3×3 Matrix{Int64}:
 9  8  7
 6  5  4
 3  2  1
In [145]:
A = round.(rand(3, 3), digits=3)
Out[145]:
3×3 Matrix{Float64}:
 0.602  0.566  0.937
 0.388  0.194  0.38
 0.605  0.077  0.005
In [146]:
vec(A) |> println # 行列をベクトルに変換する
[0.602, 0.388, 0.605, 0.566, 0.194, 0.077, 0.937, 0.38, 0.005]
In [147]:
A[:] |> println # 行列をベクトルに変換する
[0.602, 0.388, 0.605, 0.566, 0.194, 0.077, 0.937, 0.38, 0.005]

線形代数¶

ランク¶
In [148]:
A = [1.0 3.0 5.0; 6.0 8.0 3.0; 3.0 4.0 2.0];
rank(A) # ランク
Out[148]:
3
行列式¶
In [149]:
A = [1.0 3.0 5.0; 6.0 8.0 3.0; 3.0 4.0 2.0];
det(A) # 行列式
Out[149]:
-5.0
逆行列¶
In [150]:
A = [1.0 3.0 5.0; 6.0 8.0 3.0; 3.0 4.0 2.0]
inv(A) # 逆行列
Out[150]:
3×3 Matrix{Float64}:
 -0.8  -2.8   6.2
  0.6   2.6  -5.4
  0.0  -1.0   2.0
In [151]:
A * inv(A)
Out[151]:
3×3 Matrix{Float64}:
 1.0  -8.88178e-16  0.0
 0.0   1.0          0.0
 0.0   0.0          1.0
連立方程式 $A x = b$ を解く¶
In [152]:
A = [1.0 3.0 5.0; 6.0 8.0 3.0; 3.0 4.0 2.0];
b = [3, 4, 6]
A \ b |> println
[23.599999999999998, -20.2, 8.0]
In [153]:
inv(A) * b |> println # これはお勧めではない
[23.599999999999994, -20.199999999999996, 8.0]
固有値,固有ベクトル¶
In [154]:
a = [3 1; 2 4;]
F = eigen(a)
F.values  |> println
F.vectors
[2.0, 5.0]
Out[154]:
2×2 Matrix{Float64}:
 -0.707107  -0.447214
  0.707107  -0.894427

固有値の大きい順に並べ替える

In [155]:
eigenvalues, eigenvectors = eigen(a, sortby=x-> -x)
Out[155]:
Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}
values:
2-element Vector{Float64}:
 5.0
 2.0
vectors:
2×2 Matrix{Float64}:
 -0.447214  -0.707107
 -0.894427   0.707107

一般的な行列の場合の LU 分解

In [156]:
a = [3 1; 2 4;]
F = factorize(a);
In [157]:
F.L
Out[157]:
2×2 Matrix{Float64}:
 1.0       0.0
 0.666667  1.0
In [158]:
F.U
Out[158]:
2×2 Matrix{Float64}:
 3.0  1.0
 0.0  3.33333

対称行列の場合

In [159]:
B = [1.5 2 -4; 2 -1 -3; -4 -3 5]
Out[159]:
3×3 Matrix{Float64}:
  1.5   2.0  -4.0
  2.0  -1.0  -3.0
 -4.0  -3.0   5.0
In [160]:
F = factorize(B)
Out[160]:
BunchKaufman{Float64, Matrix{Float64}, Vector{Int64}}
D factor:
3×3 Tridiagonal{Float64, Vector{Float64}}:
 -1.64286   0.0   ⋅ 
  0.0      -2.8  0.0
   ⋅        0.0  5.0
U factor:
3×3 UnitUpperTriangular{Float64, Matrix{Float64}}:
 1.0  0.142857  -0.8
  ⋅   1.0       -0.6
  ⋅    ⋅         1.0
permutation:
3-element Vector{Int64}:
 1
 2
 3
特異値分解 SVD singular value decomposition¶
In [161]:
A = randn(3, 3)

using LinearAlgebra
U, S, V = LinearAlgebra.svd(A)
Out[161]:
SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}
U factor:
3×3 Matrix{Float64}:
 -0.429363  -0.199865   0.880739
 -0.874135  -0.153165  -0.4609
  0.227017  -0.967778  -0.108946
singular values:
3-element Vector{Float64}:
 1.8582231436918584
 0.8008048726012724
 0.12184918481431992
Vt factor:
3×3 Matrix{Float64}:
 0.156361  -0.707836    -0.688853
 0.151543   0.706367    -0.691434
 0.976005   0.00372246   0.217715
QR 分解¶
In [162]:
qr(A)
Out[162]:
LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}
Q factor: 3×3 LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}
R factor:
3×3 Matrix{Float64}:
 0.336588  -0.931314  -1.29523
 0.0        1.08752    0.150984
 0.0        0.0        0.495351
コレスキー分解¶
In [163]:
using Statistics
r = cor(rand(10, 3))
Out[163]:
3×3 Matrix{Float64}:
  1.0        0.355344  -0.469512
  0.355344   1.0       -0.184936
 -0.469512  -0.184936   1.0
In [164]:
c = cholesky(r)
Out[164]:
Cholesky{Float64, Matrix{Float64}}
U factor:
3×3 UpperTriangular{Float64, Matrix{Float64}}:
 1.0  0.355344  -0.469512
  ⋅   0.934736  -0.0193614
  ⋅    ⋅         0.882714
In [165]:
c.U
Out[165]:
3×3 UpperTriangular{Float64, Matrix{Float64}}:
 1.0  0.355344  -0.469512
  ⋅   0.934736  -0.0193614
  ⋅    ⋅         0.882714
In [166]:
c.U * rand(3, 3)
Out[166]:
3×3 Matrix{Float64}:
 -0.0133188  0.319893  1.13218
  0.40984    0.676506  0.403429
  0.88051    0.419873  0.00384122

集合¶

空集合¶

In [167]:
s1 = Set()
Out[167]:
Set{Any}()
In [168]:
s2 = Set([])
Out[168]:
Set{Any}()
In [169]:
s1 == s2 # どちらの定義でも同じ
Out[169]:
true

集合を定義する¶

集合の要素は任意の型が混在していてかまわない。ユニークな要素で構成される。要素の順序は不定である。

In [170]:
a = Set([1, 2, 1, "abc", 1.3, 'x'])
a |> println
Set(Any["abc", 1.3, 2, 'x', 1])
In [171]:
b = Set([2,1,3,4,2,5,2]) |> println
Set([5, 4, 2, 3, 1])

集合を対象にする関数¶

In [172]:
s = Set()
push!(s, "a")    # 要素の追加
push!(s, 2, 3.5)
s |> println
Set(Any[2, 3.5, "a"])
In [173]:
in("b", s), in(3.5, s) # 要素に含まれるか?
Out[173]:
(false, true)
In [174]:
t = pop!(s, "a") # 要素の削除
t |> println
s |> println
a
Set(Any[2, 3.5])
In [175]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
union(a, b) |> println # 和集合
Set([5, 4, 7, 2, 9, 3, 1])
In [176]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
union!(a, b) # インプレイスでの和集合
a |> println
Set([5, 4, 7, 2, 9, 3, 1])
In [177]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
intersect(a, b) |> println # 積集合
Set([3, 1])
In [178]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
intersect!(a, b) # インプレイスでの積集合
a |> println
Set([3, 1])
In [179]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
setdiff(a, b) |> println # 差集合
Set([5, 7, 9])
In [180]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
setdiff!(a, b) # インプレースでの差集合
a |> println
Set([5, 7, 9])
In [181]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
symdiff(a, b) |> println # 和集合から積集合を除く
Set([5, 4, 7, 2, 9])
In [182]:
symdiff!(a, b) # インプレースで和集合から積集合を除く
a |> println
Set([5, 4, 7, 2, 9])
In [183]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
issubset(a, b) |> println # 包含関係にあるか?
issubset(a, Set([1, 3, 5, 7, 9, 11])) |> println
false
true
In [184]:
a = Set([1,3,5,7,9])
b = Set([1,2,3,4])
issetequal(a, b) |> println # 同一か?
issubset(a, Set([1,3,5,7,9])) |> println
false
true
In [185]:
isempty(a), isempty(Set()), isempty(Set([])) # 空集合か?
Out[185]:
(false, true, true)
In [186]:
a = Set([1,3,5,7,9])
length(a) # 空集合か?
Out[186]:
5
In [187]:
a = Set([1,3,5,7,9])
empty!(a) # 空集合にする
isempty(a) |> println
a          |> println
true
Set{Int64}()

辞書¶

空の辞書¶

In [188]:
dic1 = Dict()
Out[188]:
Dict{Any, Any}()
In [189]:
dic2 = Dict([])
Out[189]:
Dict{Any, Any}()
In [190]:
dic1 == dic2 # どちらの定義でも同じ
Out[190]:
true

辞書の定義¶

In [191]:
dic = Dict("a" => 1, "foo" => "bar") # => で指定
Out[191]:
Dict{String, Any} with 2 entries:
  "a"   => 1
  "foo" => "bar"
In [192]:
Dict([("a", 1), ("foo", "bar")]) # タプルのベクトルで指定
Out[192]:
Dict{String, Any} with 2 entries:
  "a"   => 1
  "foo" => "bar"

要素の参照¶

In [193]:
dic["a"], dic[:"foo"]
Out[193]:
(1, "bar")

辞書を対象にする関数¶

In [194]:
dic = Dict()
dic[:a] = 1 # 要素の追加
dic[:foo] = "bar"
dic
Out[194]:
Dict{Any, Any} with 2 entries:
  :a   => 1
  :foo => "bar"
In [195]:
dic = Dict("a" => 1, "b" => 2)
x = pop!(dic, "a") # 要素の取り出し。取り出したものを使わないのであれば消去 delete!() と同じ
x   |> println
dic |> println
1
Dict("b" => 2)
In [196]:
dic = Dict("a" => 1, "b" => 2)
delete!(dic, "b") # 要素の削除
dic |> println
Dict("a" => 1)
In [197]:
haskey(dic, "a"), haskey(dic, "x") # キーの存否
Out[197]:
(true, false)
In [198]:
keys(dic) |> println # キーの一覧
["a"]
In [199]:
values(dic) |> println # 値の一覧
[1]
In [200]:
isempty(dic) # 辞書は空か?
Out[200]:
false
In [201]:
length(dic) # 辞書の長さ(要素数)
Out[201]:
1
In [202]:
empty!(dic) # 辞書を空にする
isempty(dic), length(dic)
Out[202]:
(true, 0)

マージ

第 1 引数,第 2 引数の両方にある要素は,第 2 引数の要素に置き換わる。

In [203]:
a = Dict("foo" => 0.0, "bar" => 42.0)
b = Dict("baz" => 17, "bar" => 4711)
merge(a, b)
Out[203]:
Dict{String, Float64} with 3 entries:
  "bar" => 4711.0
  "baz" => 17.0
  "foo" => 0.0
In [204]:
merge(b, a)
Out[204]:
Dict{String, Float64} with 3 entries:
  "bar" => 42.0
  "baz" => 17.0
  "foo" => 0.0

四則演算 + $\alpha$¶

加算¶

In [205]:
1 + 2, +(1, 2), +(1, 2, 3, 4, 5) # 和
Out[205]:
(3, 3, 15)

減算¶

In [206]:
5 - 3 , -(5, 3) # 差
Out[206]:
(2, 2)

乗算¶

In [207]:
2 * 8, *(2, 8), *(1, 2, 3, 4, 5, 6)
Out[207]:
(16, 16, 720)

乗算記号は省略できる。

In [208]:
x = 3
2x, 3.5x, 12/2x, 12/(2x), 2(x+4), 2^3x, 2^(3x)
Out[208]:
(6, 10.5, 2.0, 2.0, 14, 512, 512)

除算¶

In [209]:
14 / 3, /(14, 3) # 商
Out[209]:
(4.666666666666667, 4.666666666666667)

整数除算¶

整数除算演算子 ÷ は \ d i v tabキー で入力できる。

In [210]:
13 ÷ 4, 13 ÷ -4, -13 ÷ 4, -13 ÷ -4, 13 ÷ 2
Out[210]:
(3, -3, -3, 3, 6)

整数除算は div(x, y) もある。

In [211]:
div(13, 4), div(13, -4), div(-13, 4), div(-13, -4), div(13, 2) # 整数除算
Out[211]:
(3, -3, -3, 3, 6)

剰余¶

In [212]:
13 % 4, 13 % -4, -13 % 4, -13 % -4, 13 % 2
Out[212]:
(1, 1, -1, -1, 1)

剰余は rem(x, y) もある。rem(x, y) と x % y は同じ結果になる。

In [213]:
rem(13, 4), rem(13, -4), rem(-13, 4), rem(-13, -4), rem(13, 2) # 剰余
Out[213]:
(1, 1, -1, -1, 1)

剰余関数は mod(x, y) もある。mod(x, y) と rem(x, y) の結果は違う場合がある。

In [214]:
mod(13, 4), mod(13, -4), mod(-13, 4), mod(-13, -4), mod(13, 2)
Out[214]:
(1, -3, 3, -1, 1)

商と剰余を同時に求める divrem(x, y) がある。

In [215]:
divrem(13, 4), divrem(-13, 4), divrem(13, -4), divrem(-13, -4)
Out[215]:
((3, 1), (-3, -1), (-3, 1), (3, -1))

累乗とべき乗¶

In [216]:
2 ^ 5, 2.0 ^ 5, ^(2.0, 5)
Out[216]:
(32, 32.0, 32.0)
In [217]:
1.27 ^ 2.3, 2 ^ 0.5, ^(2, 0.5) # べき乗
Out[217]:
(1.732800474471134, 1.4142135623730951, 1.4142135623730951)

分数演算¶

有理数のままで演算される。

In [218]:
1//2 + 2//3
Out[218]:
7//6

左辺乗算演算子¶

x \ y は x の逆(逆数)と y の乗算を行う。

整数引数に対しても実数の結果を与える。

In [219]:
a = 12 \ 4, (1/12) * 4, inv(12) * 4
Out[219]:
(0.3333333333333333, 0.3333333333333333, 0.3333333333333333)

数学関数¶

床¶

In [220]:
floor(3.14), floor(Int, 3.14), floor(-3.14), floor(Int, -3.14)
Out[220]:
(3.0, 3, -4.0, -4)
In [221]:
fld(7.35, 2.8), 7.35/2.8, floor(7.35/2.8), floor(Int, 7.35/2.8)
Out[221]:
(2.0, 2.625, 2.0, 2)
In [222]:
div(7.35, 2.8), div(7.35, 2.8, RoundDown), div(7.35, 2.8, RoundUp)
Out[222]:
(2.0, 2.0, 3.0)

天井¶

In [223]:
ceil(3.14), ceil(Int, 3.14), ceil(-3.14), ceil(Int, -3.14)
Out[223]:
(4.0, 4, -3.0, -3)
In [224]:
cld(7.35, 2.8), 7.35/2.8, ceil(7.35/2.8), ceil(Int, 7.35/2.8)
Out[224]:
(3.0, 2.625, 3.0, 3)
In [225]:
div(7.35, 2.8), div(7.35, 2.8, RoundDown), div(7.35, 2.8, RoundUp)
Out[225]:
(2.0, 2.0, 3.0)

丸め¶

In [226]:
round(π, digits=5), round(2.15, digits=1), round(2.25, digits=1)
Out[226]:
(3.14159, 2.2, 2.2)
In [227]:
round(π), round(Int, 1π) # round(Int, π) はエラーになる
Out[227]:
(3.0, 3)
In [228]:
round(1.3), round(-1.3), round(1.6), round(-1.6)
Out[228]:
(1.0, -1.0, 2.0, -2.0)

切り捨て¶

In [229]:
trunc(1.3), trunc(-1.3), trunc(1.6), trunc(-1.6)
Out[229]:
(1.0, -1.0, 1.0, -1.0)

型変換¶

In [230]:
Int(12.0) # 小数点以下を含む数の Int(x) は InexactError になる
Out[230]:
12
In [231]:
Float64(12)
Out[231]:
12.0
In [232]:
float.([1, 2.3, π, ℯ]) |> println
[1.0, 2.3, 3.141592653589793, 2.718281828459045]

第 2 引数の型を第 1 引数の型にする

In [233]:
oftype(4.0, 3), oftype(4, 3.0)
Out[233]:
(3.0, 3)

第 2 引数の型を第 1 引数で指定した型にする

In [234]:
convert(Float64, 3), convert(typeof(4.0), 3)
Out[234]:
(3.0, 3.0)
In [235]:
convert(Int, 3.0), convert(typeof(4), 3.0) # convert(Int, 3.1)
Out[235]:
(3, 3)

符号¶

In [236]:
sign(10), sign(0), sign(-2)
Out[236]:
(1, 0, -1)

符号の付替¶

copysign(x, y) は x の絶対値に y の符号を付けたものを返す。

In [237]:
copysign(10, -23), copysign(-5, 6)
Out[237]:
(-10, 5)

絶対値¶

In [238]:
abs(-1.3), abs(-4), abs(0), abs(4)
Out[238]:
(1.3, 4, 0, 4)
In [239]:
14 % 3, -14 % 3, 14 % -3, -14 % -3, 14 %2
Out[239]:
(2, -2, 2, -2, 0)

平方根¶

In [240]:
sqrt(10), sqrt(123)
Out[240]:
(3.1622776601683795, 11.090536506409418)

整数平方根

sqrt() の整数部分

In [241]:
isqrt(10), isqrt(123)
Out[241]:
(3, 11)

立方根¶

In [242]:
cbrt(8), 8^(1/3), ∛8
Out[242]:
(2.0, 2.0, 2.0)

4乗根¶

In [3]:
fourthroot(16), 16^(1/4), ∜16
Out[3]:
(2.0, 2.0, 2.0)

累乗¶

次の累乗数

nextpow(x, y) は $x^n \geqq y$ である最小の $x^n$

In [243]:
nextpow(2, 1000), nextpow(13, 500)
Out[243]:
(1024, 2197)

前の累乗数

prevpow(x, y) は $x^n \leqq y$ である最大の $x^n$

In [244]:
prevpow(2, 1000), prevpow(13, 500)
Out[244]:
(512, 169)

法による累乗

In [245]:
powermod(2, 6, 5), mod(2^6, 5)
Out[245]:
(4, 4)

対数関数¶

log(b, x) により,底が b の場合に,x の対数を求める。R や Python と順序が逆なので注意。

自然対数(底が ℯ の対数)log(x),常用対数(底が 10 の対数)log10(x),底が 2 の対数 log2(x)

In [246]:
log(10, 100), log(ℯ), log10(10), log2(2)
Out[246]:
(2.0, 1, 1.0, 1.0)

指数関数¶

自然対数の逆関数 exp(x),常用対数の逆関数 exp10(x),底が 2 の対数の逆関数 exp2(x)

In [247]:
exp(1), exp10(1), exp2(1)
Out[247]:
(2.718281828459045, 10.0, 2.0)

三角関数¶

引数がラジアンの三角関数

In [248]:
sin(π/6), cos(π/6), tan(π/6)
Out[248]:
(0.49999999999999994, 0.8660254037844387, 0.5773502691896257)

引数が度の三角関数

In [249]:
sind(30), cosd(30), tand(30)
Out[249]:
(0.5, 0.8660254037844386, 0.5773502691896258)

逆三角関数¶

引数がラジアンの逆三角関数

In [250]:
asin(0.5), acos(sqrt(3)/2), atan(1/sqrt(3)), π/6
Out[250]:
(0.5235987755982989, 0.5235987755982989, 0.5235987755982989, 0.5235987755982988)

引数が度の逆三角関数

In [251]:
asind(0.5), acosd(sqrt(3)/2), atand(1/sqrt(3))
Out[251]:
(30.000000000000004, 30.000000000000004, 30.000000000000004)

双曲線関数¶

In [252]:
sinh(2), cosh(2), tanh(2)
Out[252]:
(3.6268604078470186, 3.7621956910836314, 0.9640275800758169)

逆双曲線関数¶

In [253]:
asinh(sinh(2)), acosh(cosh(2)), atanh(tanh(2))
Out[253]:
(2.0, 2.0, 2.0000000000000004)

階乗¶

In [254]:
factorial(5), prod(1:5)
Out[254]:
(120, 120)
In [255]:
factorial(20), prod(1:20)
Out[255]:
(2432902008176640000, 2432902008176640000)

ガンマ関数,対数ガンマ関数との関連

$n! \equiv \Gamma(n+1)$

In [256]:
using SpecialFunctions
gamma(6), factorial(5), exp(lgamma(6)), exp(logfactorial(5))
Out[256]:
(120.0, 120, 119.99999999999997, 119.99999999999997)

階乗はすぐに大きくなる。21! は Float64 で扱えない。factorial(big(n)) で求めることができる。

In [257]:
factorial(big(21))
Out[257]:
51090942171709440000

組み合わせの数¶

In [258]:
binomial(5, 3), factorial(5)÷factorial(3)÷factorial(2), factorial(5)/factorial(3)/factorial(2)
Out[258]:
(10, 10, 10.0)

最大公約数,最小公倍数¶

In [259]:
gcd(9797, 3589) # 最大公約数
Out[259]:
97
In [260]:
gcd(48, 128, 300) # 最大公約数
Out[260]:
4
In [261]:
lcm(48, 36) # 最小公倍数
Out[261]:
144
In [262]:
lcm(2, 3, 5, 7, 9, 11, 13) # 最小公倍数
Out[262]:
90090

ドット記法¶

通常はスカラー変数を対象とする関数を,ベクトルの要素全体に作用させ,ベクトルとして結果を得るという操作が必要な場合がある。

for ループを使って以下のように簡単に書くことができる[^2]。R や Python では for ループが遅いので,ベクトル演算を使うように言われるが,Julia ではそんなことはなく,むしろ for ループで書いたほうが実行速度が速いこともある。

In [263]:
x = Float64.([2, 3, 5, 7, 11])
for i in 1:5
    x[i] = sqrt(x[i])
end
x |> println
[1.4142135623730951, 1.7320508075688772, 2.23606797749979, 2.6457513110645907, 3.3166247903554]

別の方法はドット記法を使って,関数名.(x) とすることにより関数をベクトル対応にすることができる。

In [264]:
sqrt.([2, 3, 5, 7, 11]) |> println # 平方根を求める
[1.4142135623730951, 1.7320508075688772, 2.23606797749979, 2.6457513110645907, 3.3166247903554]

四則演算子もドット記法を使うことによって,ベクトル演算をすることができる。

In [265]:
x = [2, 3, 5, 7, 11];
y = [1, 1, 2, 3,  5];

x .+ y |> println
x  + y |> println # `+` はドットを付けなくてもベクトル演算になる
[3, 4, 7, 10, 16]
[3, 4, 7, 10, 16]
In [266]:
x .- y |> println
x  - y |> println # `-` はドットを付けなくてもベクトル演算になる
[1, 2, 3, 4, 6]
[1, 2, 3, 4, 6]
In [267]:
x .* y |> println
# x * y |> println これは MethodError になる
[2, 3, 10, 21, 55]
In [268]:
x / y # これは意図しない結果を生む
Out[268]:
5×5 Matrix{Float64}:
 0.05   0.05   0.1   0.15   0.25
 0.075  0.075  0.15  0.225  0.375
 0.125  0.125  0.25  0.375  0.625
 0.175  0.175  0.35  0.525  0.875
 0.275  0.275  0.55  0.825  1.375
In [269]:
x ./ y |> println
[2.0, 3.0, 2.5, 2.3333333333333335, 2.2]
In [270]:
x .^ y |> println
[2, 3, 25, 343, 161051]

文字列関数¶

文字列の比較¶

In [271]:
"abc" < "abcd", "xyz" == "xyz", "as" != "is"
Out[271]:
(true, true, true)

空白で区切る¶

In [272]:
s = "123 456 7890";
split(s) |> println
SubString{String}["123", "456", "7890"]

任意の文字で区切る¶

In [273]:
t = "1-2/3/4"
split.(t, r"[-/]") |> println # 区切り文字は正規表現で指定できる
SubString{String}["1", "2", "3", "4"]

1 文字ずつに分解する¶

In [274]:
u = "abc123!@#あいう統計学"
Char[u...] |> println
['a', 'b', 'c', '1', '2', '3', '!', '@', '#', 'あ', 'い', 'う', '統', '計', '学']

文字の連結¶

In [275]:
join(['a', 'b', 'c', '1', '2', '3', '!', '@', '#', 'あ', 'い', 'う', '統', '計', '学'])
Out[275]:
"abc123!@#あいう統計学"
In [276]:
join(['a', 'b', 'c', '1', '2', '3', '!', '@', '#', 'あ', 'い', 'う', '統', '計', '学'], "-")
Out[276]:
"a-b-c-1-2-3-!-@-#-あ-い-う-統-計-学"

文字列の連結¶

In [277]:
"abc" * "12345"
Out[277]:
"abc12345"
In [278]:
"123" * "abc" * "@#&" * "漢字"
Out[278]:
"123abc@#&漢字"
In [279]:
*("123", "abc", "@#&", "漢字")
Out[279]:
"123abc@#&漢字"
In [280]:
string("123", "abc", "@#&", "漢字")
Out[280]:
"123abc@#&漢字"
In [281]:
join(["123", "abc", "@#&", "漢字"])
Out[281]:
"123abc@#&漢字"
In [282]:
["a", "b", "c"] .* ["1", "2", "3"] |> println
["a1", "b2", "c3"]
In [283]:
"Var" .* string.(1:5) |> println
["Var1", "Var2", "Var3", "Var4", "Var5"]

文字列を数値に変換する¶

文字列を整数に変換する

In [284]:
parse(Int, "123")
Out[284]:
123
In [285]:
parse.(Int, ["123", "456", "7890"]) |> println
[123, 456, 7890]
In [286]:
parse.(Int, split("123 456 7890")) |> println
[123, 456, 7890]

文字列を実数に変換する

In [287]:
parse(Float64, "12.3")
Out[287]:
12.3
In [288]:
parse.(Float64, ["12.3", "4.56", "78.90"]) |> println
[12.3, 4.56, 78.9]
In [289]:
parse.(Float64, split("12.3 4.56 78.90")) |> println
[12.3, 4.56, 78.9]

数値を文字列に変換する¶

文字列に変換する

In [290]:
string(12.345), string(67890), string(-5.7)
Out[290]:
("12.345", "67890", "-5.7")
In [291]:
string.([123, 4.56, -6.78]) |> println
["123.0", "4.56", "-6.78"]

文字列のアペンド¶

第 2 引数が文字列か文字列ベクトルかで違う。

In [292]:
a = []
append!(a, "12345")
a |> println
Any['1', '2', '3', '4', '5']
In [293]:
b = []
append!(b, ["12345"])
b |> println
Any["12345"]
In [294]:
c = []
append!(c, ["12345", "abc", "@#^"])
c |> println
Any["12345", "abc", "@#^"]

文字列の繰り返し¶

In [295]:
"123"^4, "a"^5, 'x'^8
Out[295]:
("123123123123", "aaaaa", "xxxxxxxx")

連続する文字列¶

In [296]:
String(0x41:0x5A), String(0x61:0x7A)
Out[296]:
("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")

文字コード(整数)を文字へ変換¶

In [297]:
Char(65), Char(65.0), Char(26412), Char(0x672c)
Out[297]:
('A', 'A', '本', '本')

文字の文字コード¶

In [298]:
Int('A'), Float64('A'), Int('本')
Out[298]:
(65, 65.0, 26412)

パディング(ゼロ埋め)¶

In [299]:
string(123, pad=5), string(-45, pad=8)
Out[299]:
("00123", "-00000045")

文字列置換¶

In [300]:
x = 123; y = "abc"
"x = $x, sqrt(x) = $(sqrt(x)), y = $y"
Out[300]:
"x = 123, sqrt(x) = 11.090536506409418, y = abc"

文字列の逆転¶

In [301]:
reverse("1234567890abcde")
Out[301]:
"edcba0987654321"
In [302]:
reverse(["abc", "def", "ghi", "jkl", "mno"]) |> println
["mno", "jkl", "ghi", "def", "abc"]

大文字/小文字変換¶

In [303]:
lowercase("ABCdef"), uppercase("ABCdef"), titlecase("ABCdef")
Out[303]:
("abcdef", "ABCDEF", "Abcdef")

行頭,末尾の文字の切り取り¶

最後の改行文字を取る

In [304]:
chomp("Hello\n"), chomp("Hello\n\n")
Out[304]:
("Hello", "Hello\n")

先頭,末尾の文字を切り取る

In [305]:
chop("March", head = 1, tail = 2)
Out[305]:
"ar"

スライス¶

In [306]:
a = "123456789"
a[2], a[3:5], a[end], a[end-2:end], a[1:2:end], a[2:3:end]
Out[306]:
('2', "345", '9', "789", "13579", "258")
In [307]:
SubString(a, 2), SubString(a, 2, 2), SubString(a, 3, 5) # 引数が 1 個の場合は,それ以降全部になる
Out[307]:
("23456789", "2", "345")
In [308]:
b = ["abc", "def", "ghi", "jkl", "mno"]
b[2], b[2:4], b[end], b[1:2, end]
Out[308]:
("def", ["def", "ghi", "jkl"], "mno", ["abc", "def"])

部分文字列の存在¶

第 3 引数は探索を始める文字位置(省略できない)。

In [309]:
findnext("abc", "123abc5678abc", 1)
Out[309]:
4:6
In [310]:
findnext("abc", "123abc5678abc", 7)
Out[310]:
11:13

文字列が存在しないときは nothing を返す(多くのプログラミング言語では 0 や -1 を返すが Julia は違う)。

In [311]:
a = findnext("xyz", "123abc5678abc", 1)
println(a)
nothing
In [312]:
isnothing(a)
Out[312]:
true
In [313]:
findlast("abc", "123abc5678abc")
Out[313]:
11:13

文字の位置¶

In [314]:
findfirst(isequal('o'), "xylophone")
Out[314]:
4
In [315]:
a = findfirst(isequal('z'), "xylophone")
println(a)
nothing
In [316]:
findlast(isequal('o'), "xylophone")
Out[316]:
7
In [317]:
findnext(isequal('o'), "xylophone", 5)
Out[317]:
7
In [318]:
findprev(isequal('o'), "xylophone", 5)
Out[318]:
4

述語関数¶

述語関数とは「○○は△△か?」の結果を与える関数の総称で,たとえば「x は整数か?」とか「x は素数か?」のようなものである。結果は true, false である。

偶数か?¶

In [319]:
iseven(8), iseven(9)
Out[319]:
(true, false)

奇数か?¶

In [320]:
isodd(8), isodd(9)
Out[320]:
(false, true)

2 の累乗数か?¶

In [321]:
ispow2(0.5), ispow2(128), ispow2(347)
Out[321]:
(true, true, false)

型を知る¶

In [322]:
isa(1, Int)
Out[322]:
true
In [323]:
isa(1.0, Float64)
Out[323]:
true
In [324]:
isa([1, 2, 3], Array)
Out[324]:
true
In [325]:
isa([1, 2, 3], Vector)
Out[325]:
true
In [326]:
isa([1, 2, 3], Matrix)
Out[326]:
false
In [327]:
isa("1", String)
Out[327]:
true
In [328]:
isa([1 2; 3 4], Vector)
Out[328]:
false
In [329]:
isa([1 2; 3 4], Matrix)
Out[329]:
true

文字の種類¶

In [330]:
isuppercase('A')
Out[330]:
true
In [331]:
isdigit('@'), isdigit('2'), isdigit('s'), isdigit('漢') # 数字か?
Out[331]:
(false, true, false, false)
In [332]:
isletter('@'), isletter('2'), isletter('s'), isletter('漢') # 文字か?
Out[332]:
(false, false, true, true)
In [333]:
isascii('@'), isascii('2'), isascii('s'), isascii('漢') # ASCII 文字か?
Out[333]:
(true, true, true, false)
In [334]:
isnumeric('@'), isnumeric('2'), isnumeric('s'), isnumeric('漢') # 数字か?
Out[334]:
(false, true, false, false)
In [335]:
isnumeric('9'), isdigit('9') # 全角数字は numeric であるが digit ではない
Out[335]:
(true, false)
In [336]:
islowercase('a'), islowercase('A'), islowercase('a') # アルファベット小文字
Out[336]:
(true, false, true)
In [337]:
isuppercase('a'), isuppercase('A'), isuppercase('A') # アルファベット大文字
Out[337]:
(false, true, true)
In [338]:
isspace(' '), isspace('\n'), isspace('\t') # 空白文字類
Out[338]:
(true, true, true)
In [339]:
iscntrl(' '), iscntrl('\n'), iscntrl('\t') # 制御文字
Out[339]:
(false, true, true)

同じかどうか¶

In [340]:
isequal("a", "A"), isequal("a", "a"), isequal("a")("a"), "abc" == "abc"
Out[340]:
(false, true, true, true)

nothing か¶

In [341]:
isnothing(nothing), isnothing(1)
Out[341]:
(true, false)
In [342]:
a = indexin(["boo"], ["foo", "bar", "baz"])[1]
b = indexin(["bar"], ["foo", "bar", "baz"])[1]
isnothing(a), isnothing(b)
Out[342]:
(true, false)

missing か¶

Julia では欠損値は missing で表す。

In [343]:
ismissing(missing), ismissing(nothing), ismissing(NaN)
Out[343]:
(true, false, false)

NaN か¶

In [344]:
isnan(NaN), isnan(Inf)
Out[344]:
(true, false)

無限か¶

In [345]:
isinf(Inf), isinf(-Inf)
Out[345]:
(true, true)

1 か¶

型によらず,1 かどうかを判定する。

In [346]:
isone(1), isone(1.0), isone(1//1), isone(big"1")
Out[346]:
(true, true, true, true)

0 か¶

型によらず,1 かどうかを判定する。

In [347]:
iszero(0), iszero(0.0), iszero(0//1), iszero(big"0")
Out[347]:
(true, true, true, true)

実数化したものが等しいか¶

isreal(x) は isequal(x, real(x)) と同じである。

In [348]:
x = 1.23; real(x), isreal(x), isequal(x, real(x))
Out[348]:
(1.23, true, true)
In [349]:
x = 1.23+0im; real(x), isreal(x), isequal(x, real(x))
Out[349]:
(1.23, true, true)
In [350]:
x = Inf; real(x), isreal(x), isequal(x, real(x))
Out[350]:
(Inf, true, true)
In [351]:
x = -Inf; real(x), isreal(x), isequal(x, real(x))
Out[351]:
(-Inf, true, true)
In [352]:
x = NaN; real(x), isreal(x), isequal(x, real(x))
Out[352]:
(NaN, true, true)
In [353]:
x = missing; real(x), isreal(x), isequal(x, real(x))
Out[353]:
(missing, missing, true)

小さいか¶

In [354]:
isless(3, 5), isless("a", "a"), isless("blue", "red")
Out[354]:
(true, false, true)

ソートされているか¶

In [355]:
issorted([1,3,6,9]), issorted([3,2,4,9])
Out[355]:
(true, false)

辞書順の比較¶

辞書順で大きければ 1,同じならば 0,小さければ -1

In [356]:
cmp("def", "abc"), cmp("ab", "ab"), cmp("abc", "xyz")
Out[356]:
(1, 0, -1)

パスは存在するか¶

In [357]:
ispath("/Applications/julia-1.7.app")
Out[357]:
false

ディレクトリか¶

In [358]:
isdir("/Applications/julia-1.7.app")
Out[358]:
false

ファイルか¶

In [359]:
isfile("/Applications/julia-1.7.app")
Out[359]:
false
In [360]:
isfile("/Applications/Julia-1.7.app/Contents/Resources/julia/bin/julia")
Out[360]:
false

オープンされているか¶

In [361]:
isfile("testfile12345.txt") # ファイルが存在するか
Out[361]:
false
In [362]:
io = open("testfile12345.txt", "w") # 存在しないので,書き込みのためにオープンする
Out[362]:
IOStream(<file testfile12345.txt>)
In [363]:
isopen(io) # オープンされたか
Out[363]:
true
In [364]:
close(io) # クローズする
In [365]:
isopen(io) # オープンされているか--> closer(io) したのでオープンしていない
Out[365]:
false
In [366]:
ispath("testfile12345.txt") # ファイルは存在するか
Out[366]:
true
In [367]:
rm("testfile12345.txt") # 削除する
In [368]:
ispath("testfile12345.txt") # ファイルは存在するか再確認
Out[368]:
false

乱数関数¶

In [369]:
using Random

乱数の種の設定¶

In [370]:
Random.seed!(123);

シャッフル¶

In [371]:
shuffle(collect(1:10)) |> println
[8, 9, 3, 4, 1, 6, 5, 7, 2, 10]

一様乱数ベクトル¶

In [372]:
rand(4) |> println
[0.7201025594903295, 0.5736192424686392, 0.6644684787269287, 0.29536650475479964]

一様乱数行列¶

In [373]:
rand(2,3)
Out[373]:
2×3 Matrix{Float64}:
 0.276597  0.880897  0.380949
 0.983436  0.234017  0.131944

無作為抽出¶

In [374]:
rand(1:6, 10) |> println
[1, 2, 3, 5, 2, 1, 4, 2, 1, 2]
In [375]:
rand(100:120, 5) |> println
[108, 100, 101, 119, 108]
In [376]:
rand(["abc", "de", "fghi"], 5) |> println
["fghi", "de", "fghi", "abc", "fghi"]
In [377]:
rand("12345", 5) |> println
['5', '4', '1', '3', '5']
In [378]:
rand(['1', '2', '3', 'x', 'y'], 5) |> println
['2', 'y', '2', 'x', 'y']
In [379]:
rand(('x', 'y', :z), 5) |> println
Any[:z, :z, :z, 'y', 'y']

正規乱数ベクトル¶

母平均 0,標準偏差 1 の標準正規乱数¶

In [380]:
randn(4) |> println
[0.43087746656883236, -0.7088849648388045, 1.5393309737299636, -0.5020836713902217]

母平均 μ,標準偏差 σ の標準正規乱数¶

In [381]:
μ = 50; σ = 10
randn(4) .* σ .+ μ |> println
[45.17815437593204, 60.38420185234335, 44.47126184287746, 38.01480674787298]
In [382]:
round.(randn(10) .* σ .+ μ, digits=2) |> println
[37.15, 60.38, 59.78, 42.14, 48.64, 45.64, 31.04, 58.87, 50.98, 60.43]

正規乱数行列¶

母平均 0,標準偏差 1 の標準正規乱数¶

In [383]:
randn(2, 3)
Out[383]:
2×3 Matrix{Float64}:
 -0.352303  -1.12886   2.1921
 -0.634858   0.436752  1.50917

統計関数¶

In [384]:
x = [0.5, 8.0, 5.4, 8.8, 5.0, 9.8, 2.3, 2.6, 0.1, 2.0];

最小値,最大値¶

In [385]:
argmin(x), findmin(x) # 最小値のある位置,(最小値,最小値のある位置)
Out[385]:
(9, (0.1, 9))
In [386]:
argmax(x), findmax(x) # 最大値のある位置,(最大値,最大値のある位置)
Out[386]:
(6, (9.8, 6))
In [387]:
minimum(x), maximum(x) # 最小値,最大値
Out[387]:
(0.1, 9.8)
In [388]:
extrema(x) # 最小値と最大値のタプル
Out[388]:
(0.1, 9.8)

和,平均値,中央位,不偏分散,標準偏差¶

In [389]:
using Statistics # mean(), median(), var(), std() を使うときに必要
sum(x), mean(x), median(x), var(x), std(x) # 和,平均値,中央値,不偏分散,標準偏差
Out[389]:
(44.5, 4.45, 3.8, 12.21388888888889, 3.494837462442122)
In [390]:
var(x, corrected=false), std(x, corrected=false) # 不偏ではない分散と標準偏差
Out[390]:
(10.992500000000001, 3.315493930020081)

幾何平均,調和平均¶

In [391]:
using StatsBase
geomean(x), harmmean(x) # 幾何平均,調和平均
Out[391]:
(2.5391383697713596, 0.7119839536457752)

パーセンタイル値¶

In [392]:
quantile(x) |> println
[0.1, 2.075, 3.8, 7.35, 9.8]
In [393]:
quantile(x, [0, 0.25, 0.5, 0.75, 1]) |> println # 第 2 引数で q 値を指定
[0.1, 2.075, 3.8, 7.35, 9.8]
In [394]:
quantile(x, 0.95) |> println # 第 2 引数で q 値を指定
9.350000000000001

累和,累積,差分¶

In [395]:
cumsum(1:10) |> println # 累和
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
In [396]:
cumprod(1:10) |> println # 累積
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
In [397]:
diff(sort(x)) |> println # 差分
[0.4, 1.5, 0.2999999999999998, 0.30000000000000027, 2.4, 0.40000000000000036, 2.5999999999999996, 0.8000000000000007, 1.0]
In [398]:
x = [0.5, 8.0, 5.4, 8.8, 5.0, 9.8, 2.3, 2.6, 0.1, 2.0];
y = [9.5, 2.9, 0.4, 7.6, 3.8, 0.1, 9.2, 5.5, 8.8, 3.6];
cov(x, y), cov(x, y, corrected=false) # 不偏分散共分散行列,分散共分散行列
Out[398]:
(-7.580000000000002, -6.822000000000001)

相関係数,順位相関係数¶

In [399]:
cor(x, y), corspearman(x, y), corkendall(x, y) # ピアソンの積率相関係数,スピアマンの順位相関係数,ケンドールの順位相関係数
Out[399]:
(-0.6144891041342924, -0.6727272727272727, -0.5111111111111111)

missing, NaN の取り扱い¶

ベクトルから欠損値 missing を除いて集計する

In [400]:
a = [1,2, missing, 3, 4, 5]
a |> println
mean(a)
Union{Missing, Int64}[1, 2, missing, 3, 4, 5]
Out[400]:
missing
In [401]:
b = skipmissing(a)
b |> println
mean(b)
skipmissing(Union{Missing, Int64}[1, 2, missing, 3, 4, 5])
Out[401]:
3.0

ベクトルから NaN を取り除いて集計する

In [402]:
c = [3, 4, NaN, 5, 6]
d = filter(x -> !isnan(x), c)
mean(d)
Out[402]:
4.5

ベクトルから missing, NaN を除いて集計する

In [403]:
e = [3, 4, NaN, 5, missing]
Out[403]:
5-element Vector{Union{Missing, Float64}}:
   3.0
   4.0
 NaN
   5.0
    missing
In [404]:
f = filter(x -> !isnan(x), skipmissing(e))
Out[404]:
3-element Vector{Float64}:
 3.0
 4.0
 5.0
In [405]:
mean(f)
Out[405]:
4.0

関数適用後の統計量¶

関数を適用したあとの統計量

In [406]:
e = [1, 2, 3, 6, 9, 11];
mean(√, e)
Out[406]:
2.152063150513425
In [407]:
mean(sqrt, e)
Out[407]:
2.152063150513425
In [408]:
mean(sqrt.(e))
Out[408]:
2.152063150513425
In [409]:
sum(sqrt, e)
Out[409]:
12.91237890308055
In [410]:
std(sqrt.(e))
Out[410]:
0.9177957482156243

定義されているメソッド(関数)の一覧¶

In [411]:
methods(mean)
Out[411]:
# 9 methods for generic function mean from Statistics:
  • mean(r::AbstractRange{<:Real}) in Statistics at /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Statistics/src/Statistics.jl:195
  • mean(A::AbstractArray, w::UnitWeights; dims) in StatsBase at /Users/aoki/.julia/packages/StatsBase/XgjIN/src/weights.jl:672
  • mean(A::AbstractArray, w::AbstractWeights; dims) in StatsBase at /Users/aoki/.julia/packages/StatsBase/XgjIN/src/weights.jl:665
  • mean(A::AbstractArray; dims) in Statistics at /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Statistics/src/Statistics.jl:174
  • mean(A::AbstractArray{T}, w::AbstractWeights{W, T} where T<:Real, dims::Int64) where {T<:Number, W<:Real} in StatsBase at deprecated.jl:103
  • mean(f::Number, itr::Number) in Statistics at /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Statistics/src/Statistics.jl:106
  • mean(itr) in Statistics at /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Statistics/src/Statistics.jl:44
  • mean(f, A::AbstractArray; dims) in Statistics at /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Statistics/src/Statistics.jl:104
  • mean(f, itr) in Statistics at /Applications/Julia-1.10.app/Contents/Resources/julia/share/julia/stdlib/v1.10/Statistics/src/Statistics.jl:61

配列を対象とする集計関数¶

sum(), mean(), var(), std(),... は,dims= で次元を指定できる。

In [412]:
z = [1 2 3; 4 5 6]
Out[412]:
2×3 Matrix{Int64}:
 1  2  3
 4  5  6
In [413]:
sum(z, dims=1) # 列和 結果は (1, m) 行列
Out[413]:
1×3 Matrix{Int64}:
 5  7  9
In [414]:
sum(z, dims=2) # 行和 結果は (n, 1) 行列
Out[414]:
2×1 Matrix{Int64}:
  6
 15

分散共分散行列¶

In [415]:
z = [1 2 4; 4 2 5; 5 6 7; 2 4 1; 3 5 4];
cov(z)
Out[415]:
3×3 Matrix{Float64}:
 2.5  1.5   2.5
 1.5  3.2   1.05
 2.5  1.05  4.7

相関係数行列¶

In [416]:
cor(z)
Out[416]:
3×3 Matrix{Float64}:
 1.0       0.53033   0.729325
 0.53033   1.0       0.270748
 0.729325  0.270748  1.0
In [417]:
corspearman(z)
Out[417]:
3×3 Matrix{Float64}:
 1.0       0.564288  0.820783
 0.564288  1.0       0.289474
 0.820783  0.289474  1.0
In [418]:
corkendall(z)
Out[418]:
3×3 Matrix{Float64}:
 1.0       0.527046  0.737865
 0.527046  1.0       0.222222
 0.737865  0.222222  1.0

データの正規化¶

In [419]:
x = [1. 2 3; 4 5 6; 7 8 9; 10 11 12]
Out[419]:
4×3 Matrix{Float64}:
  1.0   2.0   3.0
  4.0   5.0   6.0
  7.0   8.0   9.0
 10.0  11.0  12.0
In [420]:
using StatsBase
a = fit(ZScoreTransform, x, dims=1)
Out[420]:
ZScoreTransform{Float64, Vector{Float64}}(3, 1, [5.5, 6.5, 7.5], [3.872983346207417, 3.872983346207417, 3.872983346207417])
In [421]:
b = StatsBase.transform(a, x)
Out[421]:
4×3 Matrix{Float64}:
 -1.1619    -1.1619    -1.1619
 -0.387298  -0.387298  -0.387298
  0.387298   0.387298   0.387298
  1.1619     1.1619     1.1619
In [422]:
mean(b, dims=1)
Out[422]:
1×3 Matrix{Float64}:
 0.0  0.0  0.0
In [423]:
std(b, dims=1)
Out[423]:
1×3 Matrix{Float64}:
 1.0  1.0  1.0

平均順位¶

In [424]:
x = [3,2,1,2,3,4,5,6,6,5,4,4,4,4,3,2]
tiedrank(x) |> println
[6.0, 3.0, 1.0, 3.0, 6.0, 10.0, 13.5, 15.5, 15.5, 13.5, 10.0, 10.0, 10.0, 10.0, 6.0, 3.0]
In [425]:
using StatsBase
z = [1 2 4; 4 2 5; 5 6 7; 2 4 1; 3 5 4]
Out[425]:
5×3 Matrix{Int64}:
 1  2  4
 4  2  5
 5  6  7
 2  4  1
 3  5  4
In [426]:
[tiedrank(z[:, i]) for i in 1:size(z, 2)]
Out[426]:
3-element Vector{Vector{Float64}}:
 [1.0, 4.0, 5.0, 2.0, 3.0]
 [1.5, 1.5, 5.0, 3.0, 4.0]
 [2.5, 4.0, 5.0, 1.0, 2.5]

カウント¶

条件を満たす要素が何個あるか数える。

In [427]:
count(isequal(2), [2, 1, 2, 1, 1, 3, 4, 2, 1])
Out[427]:
3
In [428]:
count([2, 1, 2, 1, 1, 3, 4, 2, 1] .== 2)
Out[428]:
3
In [429]:
count(iseven, [2, 1, 3, 4, 4, 5, 6, 7, 8])
Out[429]:
5

ユニークな要素¶

ユニークな要素を取り出す

In [430]:
unique([2, 1, 2, 1, 1, 3, 4, 2, 1]) |> println
[2, 1, 3, 4]

結果をソートすることができる。

In [431]:
sort(unique([2, 1, 2, 1, 1, 3, 4, 2, 1])) |> println
[1, 2, 3, 4]
In [432]:
Set([2, 1, 2, 1, 1, 3, 4, 2, 1]) |> println
Set([4, 2, 3, 1])

Set() の結果は unique() の結果とは違い,直接 sort() ではソートできないので,以下のようにすればよい。

In [433]:
sort([x for x in Set([2, 1, 2, 1, 1, 3, 4, 2, 1])]) |> println
[1, 2, 3, 4]

ブロードキャストとベクトル化¶

In [434]:
A = [1, 2, 3, 4, 5]
B = [1 2; 3 4; 5 6; 7 8; 9 10]

broadcast(+, A, B)
Out[434]:
5×2 Matrix{Int64}:
  2   3
  5   6
  8   9
 11  12
 14  15
In [435]:
A .+ B
Out[435]:
5×2 Matrix{Int64}:
  2   3
  5   6
  8   9
 11  12
 14  15
In [436]:
sqrt.(B)
Out[436]:
5×2 Matrix{Float64}:
 1.0      1.41421
 1.73205  2.0
 2.23607  2.44949
 2.64575  2.82843
 3.0      3.16228
In [437]:
@. sqrt(B) + A - 1.5
Out[437]:
5×2 Matrix{Float64}:
 0.5      0.914214
 2.23205  2.5
 3.73607  3.94949
 5.14575  5.32843
 6.5      6.66228
In [438]:
sqrt.(B) .+ A .- 1.5
Out[438]:
5×2 Matrix{Float64}:
 0.5      0.914214
 2.23205  2.5
 3.73607  3.94949
 5.14575  5.32843
 6.5      6.66228

変換 map()¶

In [439]:
A = [1,2,3]
map(x -> x^2, A) |> println
[1, 4, 9]
In [440]:
map(A) do x
    x += 1
end
A |> println
[1, 2, 3]

配列Aの要素を集約(加算)¶

In [441]:
A = [1,2,3]
reduce(+, A)
Out[441]:
6
In [442]:
using Statistics
vars = randn(2,3,4)
reduce(+, vars, dims=3) # 3次元配列 n x n x k
Out[442]:
2×3×1 Array{Float64, 3}:
[:, :, 1] =
 -0.474051   3.19686    0.679801
  0.753845  -0.684118  -0.808813

フィルタリング(filter)¶

In [443]:
# 3以上の要素を抽出(フィルタリング)
A = [1, 2, 3, 4, 5]
filter(x -> x >= 3, A) |> println
[3, 4, 5]
In [444]:
filter(isodd, A) |> println
[1, 3, 5]
In [445]:
A[A .>= 3] |> println
[3, 4, 5]
In [446]:
a = [2, 4, 5, 3, 2, 1, 5, 6, 4] 
deleteat!(a, findall(isequal(4), a)) |> println
[2, 5, 3, 2, 1, 5, 6]
In [447]:
filter!(x -> x != 4, a) |> println
[2, 5, 3, 2, 1, 5, 6]

ソート sort(x), sort!(x)¶

In [448]:
vec1 = [3, 2, 1, 5, 4];
a = sort(vec1);
a |> println
[1, 2, 3, 4, 5]

インプレース(破壊的)なソート sort!()

In [449]:
vec1 = [3, 2, 1, 5, 4];
b = sort!(vec1);
b |> println
[1, 2, 3, 4, 5]
In [450]:
vec1 |> println
[1, 2, 3, 4, 5]

逆順ソート sort(x , rev=true)

In [451]:
vec1 = [3, 2, 1, 5, 4];
a = sort(vec1, rev=true);
a |> println
[5, 4, 3, 2, 1]

データフレームのソート

In [452]:
using DataFrames
df = DataFrame(x = [3, 1, 2, 1], y = ["b", "c", "a", "b"]);
sort(df, :x) |> println
4×2 DataFrame
 Row │ x      y      
     │ Int64  String 
─────┼───────────────
   1 │     1  c
   2 │     1  b
   3 │     2  a
   4 │     3  b
In [453]:
sort(df, [:x, :y]) |> println
4×2 DataFrame
 Row │ x      y      
     │ Int64  String 
─────┼───────────────
   1 │     1  b
   2 │     1  c
   3 │     2  a
   4 │     3  b
In [454]:
sort(df, [:x, :y], rev=true) |> println
4×2 DataFrame
 Row │ x      y      
     │ Int64  String 
─────┼───────────────
   1 │     3  b
   2 │     2  a
   3 │     1  c
   4 │     1  b

並べ替えベクトルを返す sortperm(x)¶

In [455]:
df = DataFrame(x = [3, 1, 2, 1], y = ["b", "c", "a", "b"]);
sortperm(df, :x) |> println
[2, 4, 3, 1]
In [456]:
sortperm(df, [:x, :y]) |> println
[4, 2, 3, 1]
In [457]:
sortperm(df, [:x, :y], rev=true) |> println
[1, 3, 2, 4]

ソートの順番を決める order

In [458]:
using DataFrames
df = DataFrame(x = [-3, -1, 0, 2, 4], y = 1:5);
sort(df, order(:x, rev=true)) |> println
5×2 DataFrame
 Row │ x      y     
     │ Int64  Int64 
─────┼──────────────
   1 │     4      5
   2 │     2      4
   3 │     0      3
   4 │    -1      2
   5 │    -3      1
In [459]:
sort(df, order(:x, by=abs)) |> println
5×2 DataFrame
 Row │ x      y     
     │ Int64  Int64 
─────┼──────────────
   1 │     0      3
   2 │    -1      2
   3 │     2      4
   4 │    -3      1
   5 │     4      5

要素のある位置 index, find¶

In [460]:
a = ['a', 'b', 'c', 'b', 'd', 'a']; # 要素が1個でもベクトルにしないといけない でもないようだけど?
b = ['a', 'b', 'c'];
indexin(a, b) |> println
Union{Nothing, Int64}[1, 2, 3, 2, nothing, 1]
In [461]:
indexin(b, a) |> println
Union{Nothing, Int64}[1, 2, 3]
In [462]:
indexin('x', a) |> println
fill(nothing)
In [463]:
indexin(['x'], a) |> println
Union{Nothing, Int64}[nothing]
In [464]:
isnothing.(indexin('x', a))
Out[464]:
true
In [465]:
isnothing(nothing)
Out[465]:
true

最小値,最大値のある位置 R の which.max, which.min

In [466]:
vec2 = [3, 2, 5, 1, 6, 9, 4]
argmin(vec2), argmax(vec2)
Out[466]:
(4, 6)

searchsortedfirst(a, x) 第 3 引数により昇順または降順にソートされたリスト中で,第 2 引数より大きいか等しい最初の要素の位置。もし第 2 引数がリスト中のすべての要素より大きければ「リスト長 + 1」 を返す。

In [467]:
searchsortedfirst([1,3,5,7], 4)  # 3
Out[467]:
3
In [468]:
searchsortedfirst([1,3,5,7], 10) # 5
Out[468]:
5
In [469]:
searchsortedfirst([1,3,5,7], 3)  # 2
Out[469]:
2
In [470]:
searchsortedfirst([7,5,3,1], 4, rev=true) # 3
Out[470]:
3

searchsortedlast(a, x) 第 3 引数により昇順または降順にソートされたリスト中で,第 2 引数より小さいか等しい最後の要素の位置。もし第 2 引数がリスト中のすべての要素より小さければ 0 を返す。

In [471]:
searchsortedlast([1,3,5,7], -1)  # 0
Out[471]:
0
In [472]:
searchsortedlast([1,3,5,7], 10)  # 4
Out[472]:
4
In [473]:
searchsortedlast([1,3,5,7], 3)   # 2
Out[473]:
2
In [474]:
searchsortedlast([7,5,3,1], 4, rev=true)  # 2
Out[474]:
2

バイナリ・コンビネーション

R の e1071::bincombinations() に相当

In [475]:
all_perm(x, n) = Iterators.product((x for i = 1:n)...)
for i in all_perm([0, 1], 3)
    println(i)
end
(0, 0, 0)
(1, 0, 0)
(0, 1, 0)
(1, 1, 0)
(0, 0, 1)
(1, 0, 1)
(0, 1, 1)
(1, 1, 1)

組み合わせ

R の combn() に相当

In [476]:
using Combinatorics
for i in combinations(1:4, 2)
   println(i)
end
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]

順列

R の permutations() に相当

In [477]:
using Combinatorics
a = [1,2,3]
for i in 1:factorial(length(a))
    println(nthperm(a, i))
end
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

b の逆順列を作る  invperm(v)

In [478]:
invperm([2,3,1]) |> println
[3, 1, 2]

v が正しい順列ならば true を返す  isperm(v)

In [479]:
isperm([3,2,1,4]), isperm([3,2,1,1,3])
Out[479]:
(true, false)

インプレースで順列を作る  permute!(v, p)

In [480]:
x = [1,3,2,4,5]
permute!(x, [2,1,3,5,4]) |> println
[3, 1, 2, 5, 4]

インプレースで逆順列を作る  invpermute!(v, p)

In [481]:
x = [2,1,3,5,4]
invpermute!(x, [1,3,2,4,5]) |> println
[2, 3, 1, 5, 4]

逆順に並べたコピーを返す  reverse(v [, start=1 [, stop=length(v) ]] )

In [482]:
x = [2,1,3,5,4]
reverse(x) |> println
[4, 5, 3, 1, 2]

インプレースで逆順  reverse!(v [, start=1 [, stop=length(v) ]]) -> v

In [483]:
reverse!([5,6,4,3,5,3,1]) |> println
[1, 3, 5, 3, 4, 6, 5]

dims で指定した次元について逆順にする  reverse(A; dims::Integer)

In [484]:
z = [2 3 2 1
     3 4 2 3
     2 1 2 4
     3 2 4 6]
reverse(z, dims=1)
Out[484]:
4×4 Matrix{Int64}:
 3  2  4  6
 2  1  2  4
 3  4  2  3
 2  3  2  1
In [485]:
reverse(z, dims=2)
Out[485]:
4×4 Matrix{Int64}:
 1  2  3  2
 3  2  4  3
 4  2  1  2
 6  4  2  3

値のある場所のインデックス¶

一番大きい要素のインデックス,二番目に大きい要素のインデックス,...

つまり,昇順ソートするときに,順に取り出す要素の位置

In [486]:
d = [3, 2, 5, 1, 4];
sortperm(d) |> println
[4, 2, 1, 5, 3]

sortperm(d) を使ってソートするのはこういうこと

In [487]:
d[sortperm(d)] |> println
[1, 2, 3, 4, 5]

降順ソートするときに,順に取り出す要素の位置

sortperm(d) を使ってソートするのはこういうこと

In [488]:
rd = sortperm(d, rev=true)
d[rd] |> println
[5, 4, 3, 2, 1]

破壊的ソート。d がインプレースでソートされるので,代入しなくてよい。

In [489]:
sort!(d)
d |> println
[1, 2, 3, 4, 5]

文字列の繰り返し¶

In [490]:
"a" ^ 5, "123" ^ 3
Out[490]:
("aaaaa", "123123123")

繰り返し repeat()¶

In [491]:
repeat(["a"], 5) |> println
["a", "a", "a", "a", "a"]
In [492]:
repeat([1,2,3], 4) |> println
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
In [493]:
repeat([1, 2, 3], 3) |> println # ベクトルの繰り返し
[1, 2, 3, 1, 2, 3, 1, 2, 3]
In [494]:
repeat([1, 2, 3], inner=3) |> println # 各要素の繰り返し
[1, 1, 1, 2, 2, 2, 3, 3, 3]
In [495]:
repeat([1, 2, 3], inner=2, outer=3) |> println # 各要素の繰り返しの繰り返し
[1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]
In [496]:
repeat([1 2 3], inner=(1,2)) |> println
[1 1 2 2 3 3]
In [497]:
a = [1 2 3]
Out[497]:
1×3 Matrix{Int64}:
 1  2  3
In [498]:
repeat(a)
Out[498]:
1×3 Matrix{Int64}:
 1  2  3
In [499]:
repeat(a, outer=1)
Out[499]:
1×3 Matrix{Int64}:
 1  2  3
In [500]:
repeat(a, outer=2)
Out[500]:
2×3 Matrix{Int64}:
 1  2  3
 1  2  3
In [501]:
repeat(a, inner=(1,2), outer=(4,3))
Out[501]:
4×18 Matrix{Int64}:
 1  1  2  2  3  3  1  1  2  2  3  3  1  1  2  2  3  3
 1  1  2  2  3  3  1  1  2  2  3  3  1  1  2  2  3  3
 1  1  2  2  3  3  1  1  2  2  3  3  1  1  2  2  3  3
 1  1  2  2  3  3  1  1  2  2  3  3  1  1  2  2  3  3

R の expand.grid()¶

In [502]:
using DataFrames

arr1 = ["a", "b", "c"]
arr2 = ["d", "e", "f"]

v = vec(collect(Base.product(arr1, arr2)))
Out[502]:
9-element Vector{Tuple{String, String}}:
 ("a", "d")
 ("b", "d")
 ("c", "d")
 ("a", "e")
 ("b", "e")
 ("c", "e")
 ("a", "f")
 ("b", "f")
 ("c", "f")
In [503]:
columns = (:A, :B)
data = NamedTuple{columns}.(v)

df = DataFrame(data)
df |> println
9×2 DataFrame
 Row │ A       B      
     │ String  String 
─────┼────────────────
   1 │ a       d
   2 │ b       d
   3 │ c       d
   4 │ a       e
   5 │ b       e
   6 │ c       e
   7 │ a       f
   8 │ b       f
   9 │ c       f

正規表現¶

match()¶

In [504]:
regex = r"H.*w"
m = match(regex, "I love Halloween!")
Out[504]:
RegexMatch("Hallow")
In [505]:
isnothing(m)
Out[505]:
false
In [506]:
m.match      # 一致した文字列を取得
Out[506]:
"Hallow"
In [507]:
m.offset     # 一致した位置を取得
Out[507]:
8
In [508]:
m = match(r"[0-9]", "I love Halloween!")
In [509]:
isnothing(m)
Out[509]:
true

occursin()¶

In [510]:
occursin("ab", "fabric"), occursin("abc", "fabric")
Out[510]:
(true, false)
In [511]:
occursin.("ab", ["fabric", "non"])
Out[511]:
2-element BitVector:
 1
 0

contains()¶

contains() と occursin() は引数の順序が違うだけで,同じものである。

In [512]:
contains("fabric", "ab")
Out[512]:
true
In [513]:
contains.(["fabric", "non"], "ab")
Out[513]:
2-element BitVector:
 1
 0

findfirst()¶

In [514]:
findfirst(r"ab", "hj ab jkabs jhjhk ab")
Out[514]:
4:5
In [515]:
findfirst("ab", "hj ab jkabs jhjhk ab")
Out[515]:
4:5

findlast()¶

In [516]:
findlast("ab", "hj ab jkabs jhjhk abff iui")
Out[516]:
19:20

findall()¶

In [517]:
findall(r"ab", "hj ab jkabs jhjhk abff iui")
Out[517]:
3-element Vector{UnitRange{Int64}}:
 4:5
 9:10
 19:20
In [518]:
findall(==(2), [3, 1, 0, 2, 4, 0, 3, 5, 4, 2])
Out[518]:
2-element Vector{Int64}:
  4
 10

replace()¶

In [519]:
replace("abcdefabcdefababababa", "ab"=>"@@")
Out[519]:
"@@cdef@@cdef@@@@@@@@a"
In [520]:
replace("abcdefabcdefababababa", "ab"=>"@@", count=2)
Out[520]:
"@@cdef@@cdefababababa"
In [521]:
replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
Out[521]:
"second first"
In [522]:
sentence1 = "a!b?c'd:e;f,g.h"
replace(sentence1, r"[!?':;,.]" => "")
Out[522]:
"abcdefgh"

制御構文¶

if-end, if-else-end, if-elseif-else-end¶

プログラムは通常,上から下に順序に従って実行される。しかし,場合によって(実行されないことも含めて)実行される内容が違ったりすることがある。

単純には,条件を満たすときに実行する部分は if-end で挟んで書く。

以下の例では,a が偶数のときは a を 2 で割ったものを新たに a とすることを表している。a が奇数のときは何もしないで end の次のプログラムを実行する。

In [523]:
a = 4
if a % 2 == 0
    a = a ÷ 2
end
Out[523]:
2

a が奇数のときに実行したいものは

In [524]:
a = 5
if a % 2 == 1
    a = 3 * a + 1
end
Out[524]:
16

のように書いてもよいが,a が偶数でなければ奇数なので,これをまとめて以下のように書く。

「もし(if) a が偶数ならば 2 で割る。そうでなければ(else) 3 倍して 1 を足す」 ということである。

In [525]:
a = 4
if a % 2 == 0
    a = a ÷ 2
else
    a = 3 * a + 1
end
Out[525]:
2

Fizz-Buzz プログラムというのは,「1 から順に数字を書いていく。ただし,3 の倍数のときには数字ではなく "Fizz",5 の倍数のときには "Buzz",15 の倍数のときには "FizzBuzz" と書く」のであるが,条件が 3 通りになったので,上の if-else-end では書けない。使うのは if-elseif-else-end である。数字 x を書くとき,条件により適切なものを書く部分は以下のようになる。

この例のように,elseif は複数個書くことができる。また,場合によっては最後の else を省略できる,あるいは省略しなければならないこともある。

In [526]:
x = 17
if x % 15 == 0
    println("FizzBuzz")
elseif x % 3 == 0
    println("Fizz")
elseif x % 5 == 0
    println("Buzz")
else
    println(x)
end
17

三項演算子¶

In [527]:
x = 3
x > 0 ? true : false
Out[527]:
true
In [528]:
ifelse(x > 0, true, false)
Out[528]:
true

for ループ¶

for-end で構成される,もっとも基本的な for ループは以下のようなものである。i を 1 から 10 まで変化させて for と end で挟まれた式を評価する。

In [529]:
s = 0
for i in 1:10
    s += i
    println("i = $i, s = $s")
end
println("result = $s")
i = 1, s = 1
i = 2, s = 3
i = 3, s = 6
i = 4, s = 10
i = 5, s = 15
i = 6, s = 21
i = 7, s = 28
i = 8, s = 36
i = 9, s = 45
i = 10, s = 55
result = 55

1:10 の部分はイテラブルといわれ,おおまかにいえば要素が順に i に割り当てられる集合のようなものと言えよう。集合 Set([2, 3, 5, 7, 9, 11]) の場合には,要素には順序がないので割り当てられる順序も無作為なように見える。

In [530]:
s = 0
for i in Set([2, 3, 5, 7, 9, 11])
    s += i
    println("i = $i, s = $s")
end
println("result = $s")
i = 5, s = 5
i = 7, s = 12
i = 2, s = 14
i = 11, s = 25
i = 9, s = 34
i = 3, s = 37
result = 37

ベクトル [2, 3, 5, 7, 9, 11] の場合には,記述されている順序に従って i に割り当てられる。

イテラブルは数値に限らない。

In [531]:
for i in ["abc", 'a', 2, 3.1]
    println("i = $i")
end
i = abc
i = a
i = 2
i = 3.1

処理内容によっては,イテラブルの要素そのものと同時に何番目の要素かの情報があると便利なことがある。そのような場合には enumerate() を使う。

In [532]:
for (i, name) in enumerate(["setosa", "versicolor", "virginica"])
    println("i = $i, name = $name")
end
i = 1, name = setosa
i = 2, name = versicolor
i = 3, name = virginica

また,複数のイテラブルから対応するものを順に割り当てると便利なこともある。そのような場合には zip() を使う。

In [533]:
names = ["John", "Susan", "Kent"]
ages  = [20, 21, 26]
for (name, age) in zip( names, ages)
    println("name = $name, age = $age")
end
name = John, age = 20
name = Susan, age = 21
name = Kent, age = 26

for-end で構成される for ループは,通常はイテラブルの要素が尽きるまでくり返されるが,条件によって途中でループから抜け出したり(break),処理をしないで次の要素に対する処理へ移ったり(continue)することができる。

In [534]:
for i in 1:10
    if i%2 == 0
        continue # i が偶数なら何もしないで,次の繰り返しへ
    end
    if i > 6
        break # i が 6 になったらループから抜け出す
    end
    println("i = $i")
end
i = 1
i = 3
i = 5

while ループ¶

while-end で構成される while ループは以下のようなものである。

制御変数 i の初期化後,while ループの先頭で制御変数が条件を満たす限り,while-end の中身を実行する。

重要なのは,while-end の中で制御変数 i を更新することである。さもなければ,一旦 while ループを開始すると条件は常に満たされているので永遠にループが終わらない(無限ループ)ことになる。当然,制御変数 i を更新するとしても,それが不適切ならば同じように無限ループに陥ることになる。

In [535]:
s = 0
i = 1
while i <= 10
    s += i
    println("i = $i")
    i += 1
end
println("result = $s")
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10
result = 55

for ループの場合と同じように,条件により次のループに入ったり(continue),ループを脱出する(break)こともできる。

上の while ループは,for ループの説明で使用したものと同じ働きをする。しかし,すべての while ループが for ループで書き換えられるわけではない。

トライ,キャッチ,ファイナリー¶

例外処理(例外的な状況に対する処理)の仕組みである。

try
 (主処理)
catch
 (例外処理)
end

finallyを使用した例

 try
  (主処理)
 catch
  (例外処理)
 finally
  (最終処理) # 例外の有無に関わらず行う処理 
 end
In [536]:
function sqrt2(x)
    try
        sqrt(x)
    catch
        println("x が 負の値でした。 x = $x")
        println("絶対値を取って(正の値にして)平方根を求めます。")
        sqrt(abs(x))
    end
end
sqrt2(8), sqrt2(-9)
x が 負の値でした。 x = -9
絶対値を取って(正の値にして)平方根を求めます。
Out[536]:
(2.8284271247461903, 3.0)
In [537]:
function sqrt2(x)
    try
        sqrt(x)
    catch
        println("x が 負の値でした。 x = $x")
        println("絶対値を取って(正の値にして)平方根を求めます。")
        sqrt(abs(x))
    finally
        println("----------")
    end
end
sqrt2(8) |> println
sqrt2(-9) |> println
----------
2.8284271247461903
x が 負の値でした。 x = -9
絶対値を取って(正の値にして)平方根を求めます。
----------
3.0

エラーのときに止める

In [538]:
a = -1
a >= 0 || error("error! a should be positive a = $a")
error! a should be positive a = -1

Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] top-level scope
   @ In[538]:2

同じことであるが,以下のようにも書ける。

In [539]:
a = -1
a < 0 && error("error! a should be positive a = $a")
error! a should be positive a = -1

Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] top-level scope
   @ In[539]:2

関数¶

関数の定義は以下のようにする。

function 関数名(引数)
    関数定義
end
In [540]:
function output(x)
    println("x = $x")
end

output(4)
x = 4

関数定義が単一の式[^1]の場合には,代入形式の簡潔な構文がある。[^1]: begin-end による複合式の場合も含むが,複合式の場合には代入形式にする意味がない。

In [541]:
output2(x) = println("x = $x")

output2(6)
x = 6

引数が2個以上の場合はカンマで区切って列挙する。

また,関数は戻り値を帰す場合がある。その場合は return 戻り値 とする。

In [542]:
function euclid(m, n)
    while n != 0
         m, n = n, m % n
    end
    return m # 最大公約数
end

euclid(24, 60)
Out[542]:
12

戻り値は複数の場合もある。

また,関数の最後であれば return は省略できる。

In [543]:
function euclid2(m, n)
    mn = m * n
    while n != 0
         m, n = n, m % n
    end
    m, mn ÷ m # 最大公約数と最小公倍数
end

euclid2(24, 60)
Out[543]:
(12, 120)

引数が変数の場合は,関数の中で変更されても,その変更は呼び出し元には反映されない。

以下の例では,引数は関数を呼び出すときには 5 であり,関数内で 2 倍されて戻り値となるが,呼び出し後には元のままの 5 である。

In [544]:
function double(z)
    2z
end

a = 5
println("関数呼び出し前 a = $a")
b = double(a)
println("関数呼び出し後 a = $a")
println("関数の戻り値  b = $b")
関数呼び出し前 a = 5
関数呼び出し後 a = 5
関数の戻り値  b = 10

引数がベクトルの場合は,関数の中で変更されるとその変更は呼び出し元に反映される。以下のプログラムは,ベクトルを引数に取る。関数内で x は 2 倍され,(その時点での)x が 3 倍された戻り値が返される。

戻り値は b に代入されるが,それは引数の 2×3 倍である。

また,引数は入力時のベクトルの 2 倍になっている。このように,引数が変更される関数は最後に ! を付けるのが慣例になっている。

In [545]:
function double!(x)
    x .*= 2
    3x
end

a = [2, 5, 9]
println("関数呼び出し前 a = $a")
b = double!(a);
println("関数呼び出し後 a = $a")
println("関数の戻り値  b = $b")
関数呼び出し前 a = [2, 5, 9]
関数呼び出し後 a = [4, 10, 18]
関数の戻り値  b = [12, 30, 54]

匿名関数(無名関数,λ関数,ラムダ関数)¶

以下の例は 引数が x で,引数の 1.08 倍を計算する関数定義である。

In [546]:
price = x -> x * 1.08
Out[546]:
#19 (generic function with 1 method)
In [547]:
price(100)
Out[547]:
108.0

引数は 複数指定できる。

In [548]:
f = (x, y) -> x + y
f(1, 2), f(100, 300)
Out[548]:
(3, 400)

map() 関数の第 1 引数としても使われる。

In [549]:
map(x -> x*1.08, 100)
Out[549]:
108.0
In [550]:
map(x -> x*1.08, [100, 200, 1000])
Out[550]:
3-element Vector{Float64}:
  108.0
  216.0
 1080.0

複数行になる場合は、begin~end で囲う。

In [551]:
nebiki = x -> begin
    price = x * 0.9
    return price * 1.08
end

nebiki(1000)
Out[551]:
972.0000000000001

動的関数定義¶

In [552]:
x = 1; y = 2
arg = "x"
a = Meta.parse("func2($arg) = x + y")
eval(a)
func2(5)
Out[552]:
7