2017年12月24日 星期日

R 語言學習筆記 (二) : 矩陣

今天繼續測試 R 語言的進階資料結構中的矩陣 (matrix). 本系列之前的測試筆記參考 :

R 語言安裝
在樹莓派上安裝 R 語言
R 語言學習筆記 (一) : 基本語法與向量

在 R 語言中, 矩陣 (matrix) 是二維資料物件, 具有列 (row) 與行 (column) 兩個維度; 三維以上的資料結構則稱為陣列 (array), 因此矩陣其實是陣列的一種特例, 即矩陣是二維陣列 (但二維陣列卻不是矩陣).

矩陣的元素可以是 numeric, character, logical, complex, raw 或 NA 等型態資料; 不過因為矩陣通常用在數值運算, 因此其元素資料型別最常見的是數值 (numeric) 或複數 (complex) 型態. 矩陣運算是向量化運算, 亦即元素對元素的運算.


一. 建立矩陣物件 : 

建立矩陣有下列幾種方法 :

1. 呼叫 matrix() 函數 :

matrix(data=NA, nrow=1, ncol=1, byrow=FALSE, dimnames=NULL)

參數 :

data=資料向量或列表, 通常為 numeric 類型
nrow=列數
ncol=行數
byrow=逐列填入, 預設 FALSE 表示維逐行填入, 即第一行填完再填第二行
dimnames=列與行名稱字串向量組成的串列, 即 list(vrow, vcol)

其中前 3 個參數固定是 data, nrow, 與 ncol, 不須指名, 其餘則須指名. 例如 :

> matrix(1:12, 3, 4)    #建立 3列 * 4 行矩陣 (預設逐行填入)
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

可見預設逐行填入是先走直的再走橫的. 若 byrow 設為 TRUE, 則先走橫的再走直的, 例如 :

> matrix(1:12, 3, 4, TRUE)    #建立 3列 * 4 行矩陣 (指定逐列填入)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12

列數行數不必都指定, 只輸入列數即可, R 會自動計算行數, 例如 : 

> matrix(1:12, 3)         #只輸入列 (第二參數預設是列數)
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

> matrix(1:12, 4)          #只輸入列 (第二參數預設是列數)
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

若要在第二參數單獨指定行數, 則須指明為 ncol :

> matrix(1:12, ncol=4)     #第二參數若非列數則須指明
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

若未指定列數與行數, 則因 byrow 預設為 FALSE, 會建立一個 n*1 的單行矩陣 : 

> matrix(1:12)     #未指定列數與行數排成單行矩陣
      [,1]
 [1,]    1
 [2,]    2
 [3,]    3
 [4,]    4
 [5,]    5
 [6,]    6
 [7,]    7
 [8,]    8
 [9,]    9
[10,]   10
[11,]   11
[12,]   12

如果向量元素無規則可循必須逐一輸入, 例如 :

> matrix(c(5,12,7,0,1,3,6,14,2,8,11,9),4)
     [,1] [,2] [,3]
[1,]    5    1    2
[2,]   12    3    8
[3,]    7    6   11
[4,]    0   14    9

但是這樣輸入一長串資料可讀性不高, 可以用 byrow 方式輸入 :

> matrix(c(5,1,2,
+               12,3,8,
+               7,6,11,
+               0,14,9),4,byrow=TRUE)
     [,1] [,2] [,3]
[1,]    5    1    2
[2,]   12    3    8
[3,]    7    6   11
[4,]    0   14    9

這樣就可讀性就比較高了. 注意, 上面的三個加號 + 是按 Enter 鍵後 R 控制台自動顯示的, 表示指令尚未完全.

如果 data 參數傳入一個純量或 NA, 則 R 會套用循環規則自動複製該單一數值填充整個矩陣 :

> matrix(0,4,3)
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0
[4,]    0    0    0
> matrix(NA,4,3)
     [,1] [,2] [,3]
[1,]   NA   NA   NA
[2,]   NA   NA   NA
[3,]   NA   NA   NA
[4,]   NA   NA   NA

由上可知, 輸出矩陣時會在左方與上方標示矩陣列與行索引位置, 但矩陣可用 matrix() 的最後一個參數 dimnames 來設定列名與欄名, 其值為列與行名稱字串向量組成的串列 list(vrow, vcol), 例如 :

> matrix(1:12, 4, dimnames=list(c("R1","R2","R3","R4"),c("C1","C2","C3")))
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12

可見索引標示已經改為列名與行名了. 除了在建立矩陣時就用 dimnames 參數設定外, 也可以在建立後呼叫 rownames() 與 colnames() 分別設定或修改列名與欄名 :

> m=matrix(1:12, 4)
> m
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

> rownames(m) <- c("R1","R2","R3","R4")   #設定列名
> m
   [,1] [,2] [,3]
R1    1    5    9
R2    2    6   10
R3    3    7   11
R4    4    8   12
> colnames(m) <- c("C1","C2","C3")   #設定行名
> m
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12

或者用 dimnames() 函數一次設定或修改, 例如 :

> m=matrix(1:12, 4)
> m
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
> dimnames(m) <- list(c("R1","R2","R3","R4"),c("C1","C2","C3"))
> m
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12
> dimnames(m)     #取得矩陣維度資訊與列行名稱
[[1]]
[1] "R1" "R2" "R3" "R4"

[[2]]
[1] "C1" "C2" "C3"



2. 呼叫 dim() 設定維度將向量或列表轉成矩陣 :

矩陣的因次或維度 (dimension, 即列數與行數) 可以呼叫 dim() 函數來查詢 :

> m=matrix(1:12, 3, 4)
> dim(v)     #查詢矩陣因次
[1] 3 4              # 3 列 4 行

回應的兩個數分別為列與行. 函數 dim(v) 除了做 getter 外, 也可以做 setter, 將一個代表列數與行數的向量 c(nrow, ncol) 設定給 dim(v) 可將向量 v 轉成矩陣; 例如 :

> v=c(5,12,7,0,1,3,6,14,2,8,11,9)
> v
 [1]  5 12  7  0  1  3  6 14  2  8 11  9
> class(v)
[1] "numeric"                   #數值型態的原型向量
> dim(v)                      #向量的維度是 NULL
NULL
> dim(v) <- c(4,3)       #設定向量的維度是 4*3
> v
     [,1] [,2] [,3]
[1,]    5    1    2
[2,]   12    3    8
[3,]    7    6   11
[4,]    0   14    9
> class(v)                     #向量設定維度後變成矩陣
[1] "matrix"
> dim(v)
[1] 4 3                               #矩陣維度 4*3

但是若將向量的維度指定為一個三元素以上的維度向量, 則會變成陣列型態, 例如 :

> v=c(5,12,7,0,1,3,6,14,2,8,11,9)
> dim(v) <- c(2,3,2)    #改成三個維度
> v
, , 1

     [,1] [,2] [,3]
[1,]    5    7    1
[2,]   12    0    3

, , 2

     [,1] [,2] [,3]
[1,]    6    2   11
[2,]   14    8    9
> class(v)      # 變成 array 類型
[1] "array

除了向量外, 列表也可以轉成矩陣, 同樣也是透過呼叫 dim() 設定列表的維度 :

> l=list(5,12,7,0,1,3,6,14,2,8,11,9)   
> class(l)
[1] "list"
> dim(l)=c(4,3)
> l
     [,1] [,2] [,3]
[1,] 5    1    2 
[2,] 12   3    8 
[3,] 7    6    11
[4,] 0    14   9 
> class(l)
[1] "matrix"


3. 呼叫 rbind() 或 cbind() 將列向量或行向量組合成矩陣 :

建立矩陣的第三種方法是利用 rbind() 或 cbind() 將向量組合成矩陣, rbind() 是將向量當成矩陣的列組合起來, 故這些向量即為列向量, 例如 :

> rbind(c(1,5,9),c(2,6,10),c(3,7,11),c(4,8,12))
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

也可以先建立列向量再組合, 這樣會把列向量變數名稱作為矩陣的列名稱, 例如 :

> R1 <- c(1,5,9)      #先建立列向量
> R2 <- c(2,6,10)
> R3 <- c(3,7,11)
> R4 <- c(4,8,12)
> rbind(R1,R2,R3,R4)
   [,1] [,2] [,3]
R1    1    5    9
R2    2    6   10
R3    3    7   11
R4    4    8   12

同樣地, 也可以用 cbind() 將行向量組成矩陣, 例如 :

> cbind(c(1,2,3,4),c(5,6,7,8),c(9,10,11,12))
     [,1] [,2] [,3]
[1,]    1    5    9     
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

> C1 <- c(1,2,3,4)          #先建立行向量
> C2 <- c(5,6,7,8)
> C3 <- c(9,10,11,12)
> cbind(C1,C2,C3)
     C1 C2 C3
[1,]  1  5  9
[2,]  2  6 10
[3,]  3  7 11
[4,]  4  8 12

可見若先建立行向量再組合會把行向量變數名稱作為矩陣的行名稱.


4. 使用 diag() 建立對角矩陣 :

diag(x = 1, nrow=1, ncol)

參數如下 :

x=向量或矩陣
nrow=列數
ncol=行數

若 nrow=ncol 或只指定 nrow, 則 diag() 將建立一個以 x 為軸的對稱矩陣, 例如 :

> diag(1, nrow=5)                #ncol 不指定時等於 nrow
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
[2,]    0    1    0    0    0
[3,]    0    0    1    0    0
[4,]    0    0    0    1    0
[5,]    0    0    0    0    1

上面這種主對角元素為 1, 其餘元素均為 0 之矩陣稱為單位矩陣 I (unitary matrix). 單位矩陣之特徵值為 1, 任何矩陣與單位矩陣之內積等於本身, 即 :

A %*% I=A
I %*% A=A

下面這個 1*5 矩陣看起來像向量, 實際上是矩陣 (結構不同).

> diag(1, ncol=5)                   #nrow 預設為 1, 故建立 1*5 矩陣
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
> class(diag(1, ncol=5))
[1] "matrix"

不是方陣之對角矩陣 : 

> diag(1, nrow=5, ncol=3)   
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    1    0
[3,]    0    0    1
[4,]    0    0    0
[5,]    0    0    0
> diag(1, nrow=3, ncol=5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
[2,]    0    1    0    0    0
[3,]    0    0    1    0    0

diag() 函數第一參數傳入向量時會套用璇還規則 :

> diag(c(1,2), nrow=5)             #x=向量時套用循環規則在對稱軸上
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
[2,]    0    2    0    0    0
[3,]    0    0    1    0    0
[4,]    0    0    0    2    0
[5,]    0    0    0    0    1
> diag(1:6, nrow=5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
[2,]    0    2    0    0    0
[3,]    0    0    3    0    0
[4,]    0    0    0    4    0
[5,]    0    0    0    0    5

diag() 函數第一參數也可以傳入矩陣, 它會傳回矩陣對角元素形成之向量, 例如 :

> A <- matrix(1:16, nrow=4)
> A
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16
> v=diag(A)           #傳回對角元素
> v
[1]  1  6 11 16
> class(v)               #diag(A) 傳回向量
[1] "integer"
> is.vector(v)       
[1] TRUE



二. 存取矩陣元素 : 

與存取向量類似, 存取矩陣也是使用中 (方) 括號, 但矩陣要用兩維 m[i, j], 第一索引 i 是列, 第二索引 j 是行. 例如 :

> m=matrix(1:12, 4,3)
> dimnames(m) <- list(c("R1","R2","R3","R4"),c("C1","C2","C3"))
> m
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12
> m[2,2]    #取得第 2 列第 2 行元素
[1] 6
> m[2,]
C1 C2 C3
 2  6 10
> m[,2]      #取得第 2 行元素
R1 R2 R3 R4
 5  6  7  8
> m[2,c(2,3)]    #取得第 2 列第 2, 3 行元素
C2 C3
 6 10
> m[c(3,4),2]    #取得第 3, 4 列第 2 行元素
R3 R4
 7  8
> m[3:4,2]        #取得第 3~4 列第 2 行元素
R3 R4
 7  8

若取出之元素若維度小於 2 (例如某列或行中的幾個元素) 會降階為原型向量; 若維度等於 2 則仍為矩陣 (子矩陣). 從矩陣中取出元素時若要保留矩陣類型可在中括號內指定 drop=FALSE, 例如 :

> class(m[2,])   #取出的資料維度小於 1 變成向量
[1] "numeric"
> class(m[,2])   #取出的資料維度小於 1 變成向量
[1] "numeric"
> class(m[2:3,2:3])    #取出的資料維度等於 1 仍為矩陣
[1] "matrix
> (m[2, , drop=FALSE])
   C1 C2 C3
R2  2  6 10
> class(m[,2,drop=FALSE])     #取出元素時不降階, 仍為矩陣類型
[1] "matrix"
> (m[,2,drop=FALSE])
   C2
R1  5
R2  6
R3  7
R4  8
> class(m[2, , drop=FALSE])    #取出元素時不降階, 仍為矩陣類型
[1] "matrix"

存取矩陣元素可以使用負索引來排除不要的列或行, 負索引只是在查詢時排除特定元素而已, 原矩陣不受影響. 例如 :

> m[-2, -2]     #不要顯示第 2 列第 2 行元素
   C1 C3
R1  1  9
R3  3 11
R4  4 12
> m                 # 原矩陣不受影響
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12
> m[-c(2,3), -2]     #不要顯示第 2, 3 列第 2 行元素
   C1 C3
R1  1  9
R4  4 12
> m[-c(2:3), -2]     #不要顯示第 2~3 列第 2 行元素
   C1 C3
R1  1  9
R4  4 12

修改矩陣元素之值只要用設定運算子將向量指派給矩陣元素即可, 例如 :

> m[2:3, ] <- 99     #第 2~3 列改為 99
> m
   C1 C2 C3
R1  1  5  9
R2 99 99 99
R3 99 99 99 
R4  4  8 12
> m[1,] <- NA        #第 1 列改為 NA
> m
   C1 C2 C3
R1 NA NA NA 
R2 99 99 99
R3 99 99 99
R4  4  8 12
> m[, 3] <- c(4, 5)   #第 3 行改為 c(4, 5) 套用循環規則
> m
   C1 C2 C3
R1 NA NA  4
R2 99 99  5
R3 99 99  4
R4  4  8  5


三. 矩陣的運算 :

1. 四則運算 :

矩陣與一個純量的加減乘除運算會作用在每一個元素上, 例如 :

gt; matrix(1:12, nrow=3)
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> matrix(1:12, nrow=3) + 1
     [,1] [,2] [,3] [,4]
[1,]    2    5    8   11
[2,]    3    6    9   12
[3,]    4    7   10   13
> matrix(1:12, nrow=3) - 1
     [,1] [,2] [,3] [,4]
[1,]    0    3    6    9
[2,]    1    4    7   10
[3,]    2    5    8   11
> matrix(1:12, nrow=3) * 2
     [,1] [,2] [,3] [,4]
[1,]    2    8   14   20
[2,]    4   10   16   22
[3,]    6   12   18   24
> matrix(1:12, nrow=3) / 2
     [,1] [,2] [,3] [,4]
[1,]  0.5  2.0  3.5  5.0
[2,]  1.0  2.5  4.0  5.5
[3,]  1.5  3.0  4.5  6.0

兩個矩陣也可以做四則運算, 即對應的元素做加減乘除運算, 但先決條件是維度須一樣, 即列數相同, 行數相同, 否則會出現 "非調和陣列" 的錯誤訊息, 例如 :

&> A <- matrix(1:12, nrow=3)
> A
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> B <- matrix(1:12, nrow=3)
> B
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> A+B                   #矩陣相加為對應元素相加
     [,1] [,2] [,3] [,4]
[1,]    2    8   14   20
[2,]    4   10   16   22
[3,]    6   12   18   24
> A-B                    #矩陣相減為對應元素相減
     [,1] [,2] [,3] [,4]
[1,]    0    0    0    0
[2,]    0    0    0    0
[3,]    0    0    0    0
> A*B                     #矩陣相乘為對應元素相乘 (Hardamard 乘積)
     [,1] [,2] [,3] [,4]
[1,]    1   16   49  100
[2,]    4   25   64  121
[3,]    9   36   81  144
> A/B                      #矩陣相除為對應元素相除
     [,1] [,2] [,3] [,4]
[1,]    1    1    1    1
[2,]    1    1    1    1
[3,]    1    1    1    1
> C <- matrix(1:12, nrow=4)    #C 為 4 列 3 行矩陣
> C
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
> A+C           #C 為 4 列 3 行矩陣, A 為 3 列 4 行矩陣, 維度不同無法運算
Error in A + C : 非調和陣列

另外, 矩陣也可以與向量做四則運算, 但條件是向量的長度必須與矩陣的列數相同, 例如 :

> A <- matrix(1:6, nrow=3)  #矩陣 A 為 3 列 2 行
> A
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
> A + 1:3     #向量長度為 3, 與矩陣列數相同 : 可四則運算
     [,1] [,2]
[1,]    2    5
[2,]    4    7
[3,]    6    9
> 1:3 + A
     [,1] [,2]
[1,]    2    5
[2,]    4    7
[3,]    6    9
> A - 1:3
     [,1] [,2]
[1,]    0    3
[2,]    0    3
[3,]    0    3
> 1:3 - A
     [,1] [,2]
[1,]    0   -3
[2,]    0   -3
[3,]    0   -3
> A * 1:3
     [,1] [,2]
[1,]    1    4
[2,]    4   10
[3,]    9   18
> 1:3 * A
     [,1] [,2]
[1,]    1    4
[2,]    4   10
[3,]    9   18
> A / 1:3
     [,1] [,2]
[1,]    1  4.0
[2,]    1  2.5
[3,]    1  2.0
> 1:3 / A
     [,1] [,2]
[1,]    1 0.25
[2,]    1 0.40
[3,]    1 0.50

可見此向量是跟矩陣的每一行做運算的, 因此可以把向量看成是列向量 (雖然 R 語言的向量並無維度). 其實向量的長度只要不大於矩陣的列數就可以, 這時運算時會套用循環規則, 例如 :

> A
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
> A + 1:2     #向量長度為 2 < 矩陣列數 3 (套用循環規則)
     [,1] [,2]
[1,]    2    6
[2,]    4    6
[3,]    4    8
> A + 1:4     #向量長度為 4 > 矩陣列數 3  (無法運算)
     [,1] [,2]
[1,]    2    8
[2,]    4    6
[3,]    6    8
Warning message:
In A + 1:4 : 較長的物件長度並非較短物件長度的倍數 

這裡 A + 1:2 的第一行 [2 4 4] 是 [1 2 3] + [1 2 1] 而得, 其餘類推.

2. 矩陣的內積 : 

上面的 A*B 稱為阿達馬乘積 (Hardamard 乘積), 兩個矩陣 A 與 B 的阿達馬乘積 A*B 是對應元素相乘, 其條件是兩矩陣的維度必須相同 (即均為 m*n 矩陣); 而矩陣的內積 A%*%B 則是 A 的列與 B 的行元素的對應乘積和組成的矩陣, 因此內積可乘之條件是矩陣 A 的列數須等於矩陣 B 的行數, 亦即若矩陣 A 為 m*n, 矩陣 B 為 n*p, 則 A%*%B 結果將得到一個 m*p 的矩陣, 維度相等之方陣必定是內積可乘.  例如 :

> A <- matrix(1:6, nrow=3)    #A 為 3*2 矩陣
> A
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
> B <- matrix(1:6, nrow=2)     #B 為 2*3 矩陣
> B
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> A %*% B        #A 與 B 之內積
     [,1] [,2] [,3]
[1,]    9   19   29
[2,]   12   26   40
[3,]   15   33   51
> B %*% A        #B 與 A 之內積
     [,1] [,2]
[1,]   22   49
[2,]   28   64

執行 A 與 B 之內積運算時, A 的第一列元素與 B 的第一行對應相乘再相加, 1*1 + 4*2=9 即為結果矩陣之 [1,1] 元素, 其餘類推.

若兩個矩陣 A, B 均有行列名稱且內積可乘, 則其內積 A%*% B 將保留前者 A 的列名與後者 B 的行名作為結果矩陣之行列名稱, 例如 :

> A=matrix(1:12, 4)       #A 為 4*3 矩陣
> rownames(A) <- c("R1","R2","R3","R4")
> colnames(A) <- c("C1","C2","C3")
> A
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12
> B=matrix(1:12, 3)       #B 為 3*4 矩陣
> rownames(B) <- c("1st","2nd","3rd")
> colnames(B) <- LETTERS[1:4]      #使用大寫字母向量
> B
    A B C  D
1st 1 4 7 10
2nd 2 5 8 11
3rd 3 6 9 12
> A %*% B          # A 與B 內積會保留 A 之列名與 B 之行名
    A   B   C   D 
R1 38  83 128 173
R2 44  98 152 206
R3 50 113 176 239
R4 56 128 200 272

3. 轉置矩陣運算 t() : 

所謂轉置矩陣是將矩陣的列與行互換所成之矩陣, R 語言提供 t() 函數可執行轉置運算 (transpose), 例如 :

> A <- matrix(1:12, nrow=3)
> A
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> t(A)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
[4,]   10   11   12

一個矩陣 A 與其轉置矩陣 t(A) 因其行列互換後相同必定是內積可乘, 不論 A %*% t(A) 或 t(A) %*% 均可乘, 例如 :

> A %*% t(A)   
     [,1] [,2] [,3]
[1,]  166  188  210
[2,]  188  214  240
[3,]  210  240  270
> t(A) %*% A 
     [,1] [,2] [,3] [,4]
[1,]   14   32   50   68
[2,]   32   77  122  167
[3,]   50  122  194  266
[4,]   68  167  266  365

矩陣若有行列名稱, 則轉置時也會隨同轉置, 例如 :

> A=matrix(1:12, 4)
> rownames(A) <- c("R1","R2","R3","R4")
> colnames(A) <- c("C1","C2","C3")
> A
   C1 C2 C3
R1  1  5  9
R2  2  6 10
R3  3  7 11
R4  4  8 12
> t(A)               #轉置時行列名稱也會一起轉置
   R1 R2 R3 R4 
C1  1  2  3  4
C2  5  6  7  8
C3  9 10 11 12

4. 矩陣元素和與平均值運算 :

R 語言中提供下列函數計算矩陣之行列和與平均值 :

rowSums(x) 計算列總和
colSums(x) 計算行總和
rowMeans(x) 計算列平均
colMeans(x) 計算行平均
sum(x) 計算矩陣全部元素和
mean(x) 計算矩陣全部元素平均值

例如 :

> A <- matrix(1:6, nrow=2)
> A
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> rowSums(A)
[1]  9 12
> colSums(A)
[1]  3  7 11
> rowMeans(A)
[1] 3 4
> colMeans(A)
[1] 1.5 3.5 5.5
> sum(A)
[1] 21
> mean(A)
[1] 3.5

5. 用 det() 求矩陣之行列式值 :

行列式 (determinant) 是將方陣映射到一個純量的函數, 其值為方陣中向右對角線元素乘積和減向左對角線元素乘積和, 可用 det() 函數求得, 例如

> A <- matrix(1:4, 2)
> A
     [,1] [,2]
[1,]    1    3
[2,]    2    4
> det(A)
[1] -2
> A=matrix(1:9, 3)
> A
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> det(A)
[1] 0

注意. 只有方陣才有行列式值 :

> A <- matrix(1:6, 2)
> A
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> det(A)         #
Error in determinant.matrix(x, logarithm = TRUE, ...) :
  'x' must be a square matrix

6. 用 solve() 函數求逆矩陣 : 

所謂逆矩陣是指, 若一個 n 階方陣 A, 存在一個 n 階方陣 B 使得 A 與 B 之內積為一 n 階單位方陣, 則稱 A 為可逆, 而 B 為其逆矩陣. 注意, 可逆矩陣一定是方陣, 但方陣並不一定是可逆, 只有非奇異方陣 (即其行列式值不為 0 者) 才有逆矩陣, 參考 :

https://zh.wikipedia.org/wiki/逆矩阵

例如 :

> A=matrix(1:4, 2)
> A
     [,1] [,2]
[1,]    1    3
[2,]    2    4
> solve(A)
     [,1] [,2]
[1,]   -2  1.5
[2,]    1 -0.5

逆矩陣是很重要的矩陣運算, 例如在解線性方程組 Ax=B 時就要用到反矩陣, R 語言提供 solve() 函數來計算反矩陣 :

x=solve(A) %*% B

例如下列二元一次方程組 :

x + 3y=4
2x + 4y=6

其解即可用係數矩陣之逆矩陣與常數項矩陣之內積求得 :

> solve(A) %*% matrix(c(4,6), nrow=2)
     [,1]
[1,]    1
[2,]    1
> solve(A) %*% c(4,6)     #用向量也可以 matrix(c(4,6), nrow=2)
     [,1]
[1,]    1
[2,]    1

即其解為 x=1, y=1.

7. 用 eigen() 求特徵值與特徵向量 :

一個方陣 (square matrix) A 的特徵向量 V 是指 V 經過方陣 A 的線性變換後, 結果與 V 保持純量關係, 即 AV=eV, 其中 e 為一純量, 代表向量 V 經過線性變換後之縮放比例, 特徵值為正表示向量 V 方向不變; 反之為負表示方向相反. e 稱為方陣 A 之特徵值, V 為其特徵向量, 參考 : 

https://zh.wikipedia.org/wiki/特征值和特征向量

> A <- matrix(1:12, nrow=4)                         #建立 4*3 矩陣 (非方陣)
> eigen(A)
Error in eigen(A) : non-square matrix in 'eigen'      #方陣才有特徵值
> A <- matrix(1:9, nrow=3)                            #建立 3*3 方陣
> eigen(A)                                                           #計算特徵值與特徵向量
eigen() decomposition
$values                                                                      #特徵值
[1]  1.611684e+01 -1.116844e+00 -5.700691e-16

$vectors                                                                     #特徵向量
           [,1]       [,2]       [,3]
[1,] -0.4645473 -0.8829060  0.4082483
[2,] -0.5707955 -0.2395204 -0.8164966
[3,] -0.6770438  0.4038651  0.4082483
> V["values"]                                                        #取得特徵值
$values
[1]  1.611684e+01 -1.116844e+00 -1.303678e-15

> V["vectors"]                                                       #取得特徵向量
$vectors
           [,1]        [,2]       [,3]
[1,] -0.2319707 -0.78583024  0.4082483
[2,] -0.5253221 -0.08675134 -0.8164966
[3,] -0.8186735  0.61232756  0.4082483
> V <- eigen(A)           
> class(V)
[1] "eigen
> class(V["values"])     #特徵值是 list 類型
[1] "list"
> class(V["vectors"])    #特徵向量是 list 類型
[1] "list"

可知 eigen() 函數傳回值為 eigen 類型之物件, 其內有 values (特徵值) 與 vectors (特徵向量) 兩個屬性, 都是 list 類型資料.


四. 矩陣常用函數 :

與矩陣相關之常用函數如下表 :

 函數 說明
 matrix(data, nrow, ncol, byro)
 str(x) 顯示物件結構與內容
 length(x) 顯示矩陣元素個數
 dim(x) 顯示物件 (矩陣, 陣列, 資料框) 維度
 nrow(x) 顯示矩陣列數
 ncol(x) 顯示矩陣行數
 is.matrix(x) 檢查是否為矩陣類型
 as.matrix(x) 將物件強制轉型為矩陣類型
 rbind(v1, v2, ...) 將多個向量以列向量方式組成矩陣
 cbind(v1, v2, ...) 將多個向量以行向量方式組成矩陣
 diag(x=1, nrow, ncol) 以 x 為軸建立 nrow 列, ncol 行之矩陣 (nrow=ncol 時對稱)
 rownames(x) 取得矩陣的列名
 colnames(x) 取得矩陣的行名
 dimnames(x) 取得矩陣的維度資訊 (含列名與欄名)
 rowSums(x) 計算矩陣列總和
 colSums(x) 計算矩陣行總和
 rowMeans(x) 計算矩陣列平均
 colMeans(x) 計算矩陣行平均
 sum(x) 計算矩陣全部元素和
 mean(x) 計算矩陣全部元素平均值
 det(x) 計算方陣之行列式值
 solve(x) 求方陣之逆矩陣
 eigen(x) 計算矩陣之特徵值與特徵向量

參考 :

R语言基础:矩阵
利用 matrix 建立矩陣
矩阵基本操作
# R Tutorial : matrix
R 向量、矩陣與陣列

沒有留言:

張貼留言