niszetの日記

アナログCMOS系雑用エンジニアが頑張る備忘録系日記

(メモ) Rでmatrix(行列)の足し算では気を付ける

背景

MATLABで書かれたコードを、Rに移植したい。
しかし機能的に互換1なコードをRでまっさらから書くのはしんどい。
そうだ、pracma, signal, controlパッケージなどがあるじゃないか

niszet.hatenablog.com

うまくいかない…原因は行列の足し算にあった。

具体例

Rは要素数が1でもベクトル。ベクトルの足し算はリサイクル規則が働くので2つ目の例のように各要素に足される。
しかし行列はリサイクル規則が働かない。3番目のコードのように。
1行1列だって例外ではないのだ。4番目のコードのように。

# 行列
matrix(1:8,2,4)
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    3    5    7
#> [2,]    2    4    6    8

# 行列にスカr...ベクトルを足す
matrix(1:8,2,4)+1
#>      [,1] [,2] [,3] [,4]
#> [1,]    2    4    6    8
#> [2,]    3    5    7    9

# 列数があわないので足せない
matrix(1:8,2,4)+matrix(1:4,2,2)
#> Error in matrix(1:8, 2, 4) + matrix(1:4, 2, 2) : non-conformable arrays

# こっちも
matrix(1:8,2,4)+matrix(1,1,1)
#> Error in matrix(1:8, 2, 4) + matrix(1, 1, 1) : non-conformable arrays

カルマンフィルタのMATLABで書かれたコードを、pracmaなどのパッケージの関数に置き換えてみたところ、これは常に行列を返すようで上記4のようなことが起こったのでした。
as.vectorでmatrix(1,1,1)を変換すると下記の通り。

matrix(1,1,1)
#>      [,1]
#> [1,]    1
as.vector(matrix(1,1,1))
#> [1] 1
str(matrix(1,1,1))
#>  num [1, 1] 1
str(as.vector(matrix(1,1,1)))
#>  num 1
matrix(1,1,1)
#>      [,1]
#> [1,]    1
as.vector(matrix(1,1,1))
#> [1] 1
str(matrix(1,1,1))
#>  num [1, 1] 1
str(as.vector(matrix(1,1,1)))
#>  num 1
class(matrix(1,1,1))
#> [1] "matrix"
class(as.vector(matrix(1,1,1)))
#> [1] "numeric"
typeof(matrix(1,1,1))
#> [1] "double"
typeof(as.vector(matrix(1,1,1)))
#> [1] "double"

is.vector(matrix(1,1,1))
#> [1] FALSE
is.vector(as.vector(matrix(1,1,1)))
#> [1] TRUE

is.matrix(matrix(1,1,1))
#> [1] TRUE
is.matrix(as.vector(matrix(1,1,1)))
#> [1] FALSE

後ろの方は蛇足ですが…。

MATLABのコードはおとなしくMATLAB上で動かすことにします2

なお、昨今の記事はreprex::reprex()を使用して整形していますが、エラーが出る箇所については基本的にはNAが返ってきています。それらの行だけは通常のコンソールに打ち込んで出てきた文字列を加工しています

Enjoy!!


  1. 互換というか、同じ動きをしてくれれば良いのです

  2. なぜはじめからそうしようとしないのか。いつもお前はそうだ