non-conformable arguments の原因と直し方(行列の次元不一致)
行列の掛け算%*%は、左の行列の列数と右の行列の行数が一致していないと計算できません。次元が合わないとnon-conformable argumentsというエラーになります。
エラーメッセージの読み方
Error in m1 %*% m2 : non-conformable arguments
Error- エラー種別 — 実行中に発生しました
m1 %*% m2- 発生箇所 — エラーの原因になった呼び出し
non-conformable arguments- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 m1 <- matrix(1:6, nrow = 2, ncol = 3) 2 m2 <- matrix(1:6, nrow = 2, ncol = 3) 3 result <- m1 %*% m2 ^ 4 cat(result, "\n")
m1の列数(3)とm2の行数(2)が一致していないため掛け算できません。t(m2)で転置すれば3行2列になり計算できます。
直し方: m1 %*% m2 を m1 %*% t(m2) にします。
パターン2
1 a1 <- matrix(1:4, nrow = 2, ncol = 2) 2 a2 <- matrix(1:6, nrow = 2, ncol = 3) 3 result <- a2 %*% a1 ^ 4 cat(result, "\n")
a2の列数(3)とa1の行数(2)が一致しないため、a2 %*% a1は計算できません。掛ける順序を入れ替える必要があります。
直し方: a2 %*% a1 を a1 %*% a2 にします。
パターン3
1 p <- matrix(1:9, nrow = 3, ncol = 3) 2 q <- matrix(1:4, nrow = 2, ncol = 2) 3 result <- p %*% q ^ 4 cat(result, "\n")
pの列数(3)とqの行数(2)が一致しないため、次元の合う行列に置き換える必要があります。
直し方: p %*% q を p %*% matrix(1:9, nrow = 3, ncol = 3) にします。
パターン4
1 x1 <- matrix(1:6, nrow = 3, ncol = 2) 2 x2 <- matrix(1:6, nrow = 3, ncol = 2) 3 result <- x1 %*% x2 ^ 4 cat(result, "\n")
x1の列数(2)とx2の行数(3)が合わないため、t(x2)で転置して2行3列にする必要があります。
直し方: x1 %*% x2 を x1 %*% t(x2) にします。
パターン5
1 u <- matrix(1:8, nrow = 2, ncol = 4) 2 v <- matrix(1:8, nrow = 2, ncol = 4) 3 result <- u %*% v ^ 4 cat(result, "\n")
uの列数(4)とvの行数(2)が一致しないため、そのままでは%*%が計算できません。
直し方: u %*% v を u %*% t(v) にします。
よくある誤解
「行列同士なら形が違っても要素ごとに掛けてくれるはず」という思い込みは誤りです。%*%は数学的な行列積であり、要素ごとの掛け算がしたい場合は*を使う必要があります。次元を確認せずに%*%を使うとエラーになります。
実務での勘所
Rには「行列」という独立したデータ型が実は存在しません。行列は、dim(次元)という属性が追加された、ただのベクトルです。この事実は*(要素ごとの掛け算)の挙動にも表れていて、次元の違う行列同士で*を使うと、行列としての整合性チェックではなく、通常のベクトルのリサイクルルールがそのまま適用されます。%*%(行列積)だけが本当の意味で次元を厳密にチェックする、数学的な行列演算です。行列がベクトルの上に成り立つ薄い抽象化だと知っておくと、こうした挙動の違いに納得がいきます。