A Blog Entry on Bayesian Computation by an Applied Mathematician
$$
$$
1 概観
1.1 すべてはベクトルである
データ型 logical
, integer
, double
, complex
, character
, raw
は全てベクトルと理解される.1 逆に,全てのベクトルはこの6つのいずれかの atomic data type を持つ.2
4.2
, four point two
はいずれもデータ型こそ違えど長さ1のベクトルである.
1.2 他のデータ型との関係
全てはベクトルで,行列も配列もリストも,それに特殊な属性を付与したもの.
1.2.1 行列と配列
dim
属性を持つベクトルのことである.各次元に名前がつくとdimnames
属性も持つ.
1.2.2 リスト
リストは各要素のデータ型が異なっていても良く,“generic vector” というべきものである.
ベクトルは基本横で[1]
という行の名前の後に表示される,行列はそのdim
属性のために基本縦で[,1]
と indexing される.indexing の表示の違いでクラスの違いがわかる.
まずベクトルの時点で定義される演算を紹介し,インデックスを紹介する.全てのオブジェクトはベクトルなので,ベクトルをベクトルでインデックスするという奇怪な状況が発生する.また R では演算のほとんどがベクトル化されていて,これを使いこなすことが高速化の最初の手法になる. 次に行列を定義し,行列特有の演算を見る.
2 ベクトル
スカラーなどの概念はない,全てはベクトル. 文字列も,character
modeの長さ1ベクトル.
2.1 構成
- 基本的にはベクトルのためのコンストラクタ
c(arg1,arg2,...)
を用いる.実は浮動小数点モードを生成する.- 引数もベクトルなので,本質は concatenation
- データ型が強制される,これが list との違い.
a:b
:a<b
ならば増加,a>b
ならば減少の,step=1
のベクトルの生成.実は整数モードを生成する.seq(from=1,to=1,by=((to - from)/(length.out - 1)))
- 上の方法だと
1:0
は[1] 1 0
を返すので安全でない. seq(NULL)
はNULL
を返すので安全.
- 上の方法だと
rep(y,times=n,each,length.out)
times
:=3
でn
回繰り返す.each
:=3
とすると各要素を3回繰り返す.length.out
:=3
とすると出力の長さを制限
- 要素ごとに代入したい場合は宣言が必要(ベクトルを指すと判明していないポインタに向かって indexing をする
y[2]
という書き方は禁忌).y <- vector(length=n)
としてポインタを作ってから,y[1]<-5
などと代入していく.- ベクトルの再割り当ては時間がかかるので,関数定義で返り値のためにベクトルの積み上げをしたい場合は,
ret <- vector(length=n)
とした方がいい.返す前にret <- ret[1:n]
として未使用部分を無くすために再割り当てをして2回で済ませるのがいい.
- ベクトルの再割り当ては時間がかかるので,関数定義で返り値のためにベクトルの積み上げをしたい場合は,
2.2 単項演算 \(V\to V\)
- 操作
rev(x)
:反転t(x)
:転置
- 表示
head(x[, n=6L])
tail(x[, n=6L])
2.3 index 付与:自分で index を変えられる.
names
属性を付与できるが,リストにはならない.names(x) <-
:colnames か rownames か,どちらか適切な方.names(x) <- NULL
:削除.
2.4 単項演算 \(V\to K\):統計的特徴の抽出
- 長さ:
length(x)
- 行列などに対しては,属性を外してベクトルと見て演算して,属性を戻すとかそういう感じ.
mean(a, na.rm=F)
:算術平均.na.rm=T
でNA
があっても適用可能になる.sum(a)
:総和prod(a)
:総積max(a)
:sd(x)
:standard deviation
2.5 単項演算 \(V\to2\):条件
all(expr)
:expr の結果である logical vector が,全てT
かどうかを判定して長さ1ベクトルを返すany(expr)
:expr の結果である logical vector が,T
が存在するかを判定して長さ1ベクトルを返す
2.6 indexing:ベクトルの構成法3つ:
,c
,seq
に対応した indexing 法がある.
y[c(1,3,4)]
:scaler は退化したベクトルなのでこれがあるべき姿y[-c(1,3,4)]
:除外は負数を用いる.y[-length(y)]
は最後の要素の除外.y[-1:-2]
は1,2番目の除外.tail(x,[n=]1)
:右後ろから indexing
2.7 数値演算 \(V^2\to V\)
- 同次元演算
a+b
,a-b
a*b
:Hadamard積,a/b
a %*% b
:内積%o%
:外積%/%
:整数除算a^b
:冪で,**
でも実行できるが非推奨.%%
:mod.情報落ちを検出したら警告が出るようになっている.
- recycle:長さがどちらかの定数倍である時,演算を繰り返す.
2.8 文字列演算
paste(“str1”, “str2”)
:concatenationstrsplit(x, split, fixed = FALSE, perl = FALSE, useBytes = FALSE)
ベクトルは C の配列のように,連続的に格納されているので,要素の挿入や削除は新しく作るのと等価.実装は C の pointer と同じで,再代入はポインタの指す先を変えることで再割り当てを実現する.
3 行列
dim
属性(ncol
とnrow
)のついたベクトルで,縦に並んだベクトルをdim
属性を参照しながら横にずらしながら構成される.
3.1 構成
- ベクトルへの属性付与による構成
- ベクトルに
dim
属性を付与するコンストラクタmatrix([data=]a,[nrow=]m,[ncol=]n)
a
が scaler の場合m×n
をa
-fill する,a
がベクトルの場合m×n
に fill していく.- fill の順番は列ごとで,
byrow=TRUE
とすると行ごとになる. - この逆変換は
as.vector(A)
- ベクトルに
- ベクトルの結合による構成
rbind(a,b,c)
:行ベクトルとして結合,あるいは行列の横結合.cbind(a,b,c)
:列ベクトルとして結合,あるいは行列の縦結合.dim(x) <- c(n,m)
:ベクトルに次元のデータを加えて,行列に変換する.
- メモリ確保は
matrix(nrow=a,ncol=b)
でなされる.
3.2 操作
rownames(), colnames() <- name
:名前をつけられる.t(A)
:転置
3.3 indexing 周り
dim(A)
:返り値は長さ2のベクトルnrow(A)=dim(A)[1]
ncol(A)=dim(A)[2]
A[行,列]
:空欄を渡すと走る,長さ2以上のベクトルを渡すと複数選択[,2]
などでも行ベクトルで帰ってくる.これは全てのベクトルは横で表示されるから.[n]
だと,列を繋げた順序についての indexing で,要素が返ってくる.
- 抽出した部分行列に値が部分代入できる.
3.4 一項演算
- ノルム
norm(A [,type=c(“o”, ”I”, ”F”, ”M”, ”2”)])
- one, infinity, flobenius = Eucleadean as a vector, maximum modulus,
2
はspectral norm. - \(l^2\)-ノルムは
sqrt(a %*% a)::matrix
でいける
- one, infinity, flobenius = Eucleadean as a vector, maximum modulus,
- 正方行列
det(A)
sum(diag(A))
:\(\operatorname{Tr}\)
3.5 二項演算
同次元演算
A+B
,A-B
A*B
,A/B
:Hadamard積A %*% B
:行列積
逆行列
solve(A)
一般化逆行列 (Moore-Penrose pseudoinverse)
library(MASS) ginv(A)
4 generic operator
行列はベクトルなので,ほとんどの関数はベクトルだと思って作用する.属性を外してベクトルと見て演算して,属性を戻すとかそういう感じ.
4.1 ベクトルと行列で挙動が違う generic 単項関数 \(K^n\to V\)
diag(x)
:引数がベクトルなら対角行列の作成.diag(rep(1,n))=En
.行列ならベクトルを返す.
4.2 ベクトルも行列も同等に扱う二項演算
- +, -:長さが整数倍ならば,repしてから足す.
- Hadamard積
*
:scaler と行列ならば普段の積.%*%
ではエラーになる. %*%
:これは数学でも generic よね.xA=行ベクトル
,Ax=列ベクトル
と返り値が定まり,x
の縦横に依らない.
solve(A,B)
:B
がベクトル \(b\) の時,\(Ax=b\) を解く.行列のときは \(AX=B\) を解く.B
を省略すると対角行列とみなされ,したがって解は \(X=A^{-1}\)
4.3 数学関数はベクトル化されている.
sin()
,exp()
,abs()
,sqrt()
,log()
,log10()
,acos()
,sinpi()
1:10*2
は(1:10)*2
だが,1:10^2
は1:100
log([x=]b,[base=exp(1)])
acos
:逆三角関数sinpi(3/2)
:sin(pi*3/2)
に同じ
round()
,floor()
,ceiling()
factorial()
x>3
などの評価:条件評価も実際は関数.3
が recycle されてx
と同じ長さになる.- point-wise に評価が行われて,
- logical のベクトルを返す.
- 複数のベクトルを値に取る関数
pmax()
cumsum()
,cumprod()
4.4 関数のベクトル化
sapply(x,f)
f
をx
の各要素に適用し,返り値を行列とする.f
がベクトルの長さを伸ばすような関数だった場合,行列化処理と合成するのが自然で,これを勝手にやってくれる.
5 配列
\(n\) 次元リストで,一番一般的なデータ構造.
- 構成
array(data=NA, dim=length(data), dimnames=NULL)
dim=c(3,4,2)
などができる.dimnames
はもともと数字で,,,1
という調子で切り出して表示される(list みたいな)