5.2 R 행렬 함수

5.2.1 t()

t(x)는 행렬 x의 전치행렬(행과 열이 서로 바뀜)을 반환합니다.

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

5.2.2 diag()

diag(x = 1, nrow, ncol, names = TRUE)는 대각행렬을 반환합니다.

# 주대각선의 원소가 모두 1인(단위행렬) 3x3 대각행렬
diag(3)  
#>      [,1] [,2] [,3]
#> [1,]    1    0    0
#> [2,]    0    1    0
#> [3,]    0    0    1

# 주대각선의 원소가 모두 10인 3x4 대각행렬
diag(10, 3, 4)
#>      [,1] [,2] [,3] [,4]
#> [1,]   10    0    0    0
#> [2,]    0   10    0    0
#> [3,]    0    0   10    0

# 주대각선의 원소를 지정한 대각행렬
diag(c(2, 5, 3, 1))
#>      [,1] [,2] [,3] [,4]
#> [1,]    2    0    0    0
#> [2,]    0    5    0    0
#> [3,]    0    0    3    0
#> [4,]    0    0    0    1

# 행렬 x의 대각행렬
(x = matrix(c(1,3,-2, 5, 7, -3, 1, 0, 1), 3, 3))
#>      [,1] [,2] [,3]
#> [1,]    1    5    1
#> [2,]    3    7    0
#> [3,]   -2   -3    1
diag(x)
#> [1] 1 7 1

5.2.3 %*%

x %*% y는 행렬 x와 행렬 y의 곱셈 결과를 반환합니다.

(x <- 1:4)
#> [1] 1 2 3 4
(y <- diag(x))
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    0    0    0
#> [2,]    0    2    0    0
#> [3,]    0    0    3    0
#> [4,]    0    0    0    4
(z <- matrix(1:12, ncol = 3, nrow = 4))
#>      [,1] [,2] [,3]
#> [1,]    1    5    9
#> [2,]    2    6   10
#> [3,]    3    7   11
#> [4,]    4    8   12

x %*% x
#>      [,1]
#> [1,]   30
y %*% z
#>      [,1] [,2] [,3]
#> [1,]    1    5    9
#> [2,]    4   12   20
#> [3,]    9   21   33
#> [4,]   16   32   48
y %*% x
#>      [,1]
#> [1,]    1
#> [2,]    4
#> [3,]    9
#> [4,]   16
x %*% z
#>      [,1] [,2] [,3]
#> [1,]   30   70  110

5.2.4 outer()

outer(x, y, FUN = "*", ...)는 두 벡터 또는 배열의 외적(outer product)를 반환합니다. 외적이란 x에 y의 전치행렬을 곱한 결과입니다.
outer(x, y)x %*% t(y)와 동일하며, x%o%y와 동일합니다.

(x <- 1:4)
#> [1] 1 2 3 4
(y <- 5:8)
#> [1] 5 6 7 8
outer(x, y)
#>      [,1] [,2] [,3] [,4]
#> [1,]    5    6    7    8
#> [2,]   10   12   14   16
#> [3,]   15   18   21   24
#> [4,]   20   24   28   32
x %*% t(y)
#>      [,1] [,2] [,3] [,4]
#> [1,]    5    6    7    8
#> [2,]   10   12   14   16
#> [3,]   15   18   21   24
#> [4,]   20   24   28   32
x%o%y
#>      [,1] [,2] [,3] [,4]
#> [1,]    5    6    7    8
#> [2,]   10   12   14   16
#> [3,]   15   18   21   24
#> [4,]   20   24   28   32

outer(x, y, FUN = "*", ...)에서 FUN = "*"로 인해 곱셈을 합니다. 만일 기본값인 *을 +로 변경하면 덧셈을 하게 됩니다.

outer(x, y, FUN = "+")
#>      [,1] [,2] [,3] [,4]
#> [1,]    6    7    8    9
#> [2,]    7    8    9   10
#> [3,]    8    9   10   11
#> [4,]    9   10   11   12

5.2.5 solve()

solve(a, b, ...)는 수식 a %*% x = b에서 x를 구하여 반환합니다. 만일 b를 지정하지 않으면 a의 역행렬을 반환합니다.

(a <- matrix(c(1, 3, -2, 5, 7, -3, 1, 0, 1), 3, 3))
#>      [,1] [,2] [,3]
#> [1,]    1    5    1
#> [2,]    3    7    0
#> [3,]   -2   -3    1
(b <- c(2, -1, 1))
#> [1]  2 -1  1

# ax=b에서 x를 구하여 반환
solve(a, b)  
#> [1] -5  2 -3

# a의 역행렬을 반환환
solve(a)
#>       [,1]  [,2]  [,3]
#> [1,] -2.33  2.67  2.33
#> [2,]  1.00 -1.00 -1.00
#> [3,] -1.67  2.33  2.67

5.2.6 rowSums()

rowSums(x, na.rm = FALSE, dims = 1)는 숫자를 담고 있는 2차원 이상의 배열 또는 데이터프레임 x의 행 합계를 반환합니다.

(x <- matrix(c(1, 3, -2, 5, 7, -3, 1, 0, 1), 3, 3))
#>      [,1] [,2] [,3]
#> [1,]    1    5    1
#> [2,]    3    7    0
#> [3,]   -2   -3    1
rowSums(x)
#> [1]  7 10 -4
a <- 1:5
b <- 1:5*2
c <- 1:5*3
df <- data.frame(a, b, c)
df
#>   a  b  c
#> 1 1  2  3
#> 2 2  4  6
#> 3 3  6  9
#> 4 4  8 12
#> 5 5 10 15

rowSums(df)
#> [1]  6 12 18 24 30

5.2.7 colSums()

colSums (x, na.rm = FALSE, dims = 1)은 숫자를 담고 있는 2차원 이상의 배열 또는 데이터프레임 x의 열 합계를 반환합니다.

(x <- matrix(c(1, 3, -2, 5, 7, -3, 1, 0, 1), 3, 3))
#>      [,1] [,2] [,3]
#> [1,]    1    5    1
#> [2,]    3    7    0
#> [3,]   -2   -3    1

colSums(x)
#> [1] 2 9 2
a <- 1:5
b <- 1:5*2
c <- 1:5*3
df <- data.frame(a, b, c)
df
#>   a  b  c
#> 1 1  2  3
#> 2 2  4  6
#> 3 3  6  9
#> 4 4  8 12
#> 5 5 10 15

colSums(df)
#>  a  b  c 
#> 15 30 45

5.2.8 rowMeans()

rowMeans(x, na.rm = FALSE, dims = 1)는 숫자를 담고 있는 2차원 이상의 배열 또는 데이터프레임 x의 행 평균을 반환합니다.

(x <- matrix(c(1, 3, -2, 5, 7, -3, 1, 0, 1), 3, 3))
#>      [,1] [,2] [,3]
#> [1,]    1    5    1
#> [2,]    3    7    0
#> [3,]   -2   -3    1
rowMeans(x)
#> [1]  2.33  3.33 -1.33
a <- 1:5
b <- 1:5*2
c <- 1:5*3
df <- data.frame(a, b, c)
df
#>   a  b  c
#> 1 1  2  3
#> 2 2  4  6
#> 3 3  6  9
#> 4 4  8 12
#> 5 5 10 15

rowMeans(df)
#> [1]  2  4  6  8 10

5.2.9 colMeans()

colMeans (x, na.rm = FALSE, dims = 1)은 숫자를 담고 있는 2차원 이상의 배열 또는 데이터프레임 x의 열 합계를 반환합니다.

(x <- matrix(c(1, 3, -2, 5, 7, -3, 1, 0, 1), 3, 3))
#>      [,1] [,2] [,3]
#> [1,]    1    5    1
#> [2,]    3    7    0
#> [3,]   -2   -3    1

colMeans(x)
#> [1] 0.667 3.000 0.667
a <- 1:5
b <- 1:5*2
c <- 1:5*3
df <- data.frame(a, b, c)
df
#>   a  b  c
#> 1 1  2  3
#> 2 2  4  6
#> 3 3  6  9
#> 4 4  8 12
#> 5 5 10 15

colMeans(df)
#> a b c 
#> 3 6 9

5.2.10 nrow(), ncol()

  • nrow(x)는 행의 갯수를 반환합니다.
  • ncol(x)는 열의 갯수를 반환합니다.
  • NROW(x)는 행의 갯수를 반환합니다. (벡터 계산 가능)
  • NCOL(x)는 열의 갯수를 반환합니다. (벡터 계산 가능)
x <- matrix(1:12, 3, 4)
nrow(x)
#> [1] 3
ncol(x)
#> [1] 4
NROW(x)
#> [1] 3
NCOL(x)
#> [1] 4
(x <- array(1:24, dim = c(3,4,2)))  # 3행*4열의 3차원 배열
#> , , 1
#> 
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    4    7   10
#> [2,]    2    5    8   11
#> [3,]    3    6    9   12
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3] [,4]
#> [1,]   13   16   19   22
#> [2,]   14   17   20   23
#> [3,]   15   18   21   24
nrow(x)
#> [1] 3
ncol(x)
#> [1] 4

NROW와 NCOL은 행렬이 아닌 벡터도 계산합니다.

x <- 1:12
nrow(x)
#> NULL
NROW(x)
#> [1] 12
ncol(x)
#> NULL
NCOL(x)
#> [1] 1

5.2.11 det()

det(x)는 행렬 x의 행렬식을 구하여 반환합니다. 행렬식은 정방행렬(nxn 행렬)인 경우에만 구할 수 있습니다. \(det \begin{pmatrix}a&b\\c&d\end{pmatrix} = ad-bc\)

(x <- matrix(1:4, nrow = 2))
#>      [,1] [,2]
#> [1,]    1    3
#> [2,]    2    4
det(x)
#> [1] -2

5.2.12 eigen()

eigen(x, symmetric, only.values = FALSE, EISPACK = FALSE)는 행렬 x의 고유값과 고유벡터를 반환합니다.

고유값과 고유벡터는 행렬 A에 대하여 \(Av = \lambda v\) 등식을 만족하는 상수와 열벡터입니다. 등식에서 v는 고유벡터이고 \(\lambda\)는 고유값입니다. 고유값과 고유벡터는 정방행렬(nxn 행렬)인 경우에만 구할 수 있습니다.

(x <- matrix(1:4, nrow = 2))
#>      [,1] [,2]
#> [1,]    1    3
#> [2,]    2    4
eigen(x)
#> eigen() decomposition
#> $values
#> [1]  5.372 -0.372
#> 
#> $vectors
#>        [,1]   [,2]
#> [1,] -0.566 -0.909
#> [2,] -0.825  0.416

5.2.13 svd()

svd(x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE)는 행렬 x의 특이값을 분해하여 그 결과를 반환합니다.

고유값 분해는 정방행렬(nxn 행렬)인 경우에만 가능합니다. 이를 직사각행렬(mxn행렬)에서도 가능하게 만든 것이 특이값 분해(SVD: Singular Value Decomposition)입니다.

\(M = UDV^T\)

x <- matrix(c(0, 0, 0, 1, 1, 0, 0, 0,
              1, 0, 0, 1, 1, 0, 0, 0,
              0, 0, 0, 1, 1, 0, 0, 0,
              1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1,
              0, 0, 0, 1, 1, 0, 0, 0,
              0, 0, 0, 1, 1, 0, 0, 0,
              0, 0, 0, 1, 1, 0, 0, 0),
            byrow = TRUE, nrow = 10)
x
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#>  [1,]    0    0    0    1    1    0    0    0
#>  [2,]    1    0    0    1    1    0    0    0
#>  [3,]    0    0    0    1    1    0    0    0
#>  [4,]    1    1    1    1    1    1    1    1
#>  [5,]    1    1    1    1    1    1    1    1
#>  [6,]    1    1    1    1    1    1    1    1
#>  [7,]    1    1    1    1    1    1    1    1
#>  [8,]    0    0    0    1    1    0    0    0
#>  [9,]    0    0    0    1    1    0    0    0
#> [10,]    0    0    0    1    1    0    0    0
x_svd <- svd(x)
x_svd
#> $d
#> [1] 6.06e+00 2.75e+00 8.48e-01 2.84e-16 2.47e-31 4.47e-33 1.64e-49 5.91e-67
#> 
#> $u
#>         [,1]   [,2]    [,3]      [,4]      [,5]      [,6]      [,7]      [,8]
#>  [1,] -0.153  0.385  0.1692  8.94e-01 -7.18e-16 -1.67e-16  2.78e-17 -5.55e-17
#>  [2,] -0.208  0.323 -0.9231 -2.78e-16 -1.18e-17 -9.03e-18 -1.42e-17 -1.61e-18
#>  [3,] -0.153  0.385  0.1692 -2.24e-01 -8.64e-01 -6.47e-02 -3.13e-16  3.69e-17
#>  [4,] -0.458 -0.197  0.0344  5.55e-17 -6.47e-02  8.64e-01 -2.67e-16 -1.67e-16
#>  [5,] -0.458 -0.197  0.0344  0.00e+00  2.16e-02 -2.88e-01  8.16e-01 -3.43e-18
#>  [6,] -0.458 -0.197  0.0344  0.00e+00  2.16e-02 -2.88e-01 -4.08e-01  7.07e-01
#>  [7,] -0.458 -0.197  0.0344  0.00e+00  2.16e-02 -2.88e-01 -4.08e-01 -7.07e-01
#>  [8,] -0.153  0.385  0.1692 -2.24e-01  2.88e-01  2.16e-02  8.51e-17  4.65e-18
#>  [9,] -0.153  0.385  0.1692 -2.24e-01  2.88e-01  2.16e-02  8.51e-17  4.65e-18
#> [10,] -0.153  0.385  0.1692 -2.24e-01  2.88e-01  2.16e-02  8.51e-17  4.65e-18
#> 
#> $v
#>        [,1]   [,2]    [,3]      [,4]    [,5]     [,6]      [,7]      [,8]
#> [1,] -0.337 -0.169 -0.9262  0.00e+00  0.0000  0.00000  0.00e+00  0.00e+00
#> [2,] -0.303 -0.287  0.1624  7.74e-01 -0.4483  0.01146  0.00e+00  0.00e+00
#> [3,] -0.303 -0.287  0.1624 -6.28e-01 -0.6370  0.01628  0.00e+00  0.00e+00
#> [4,] -0.463  0.530  0.0718 -3.89e-16  0.0181  0.70688 -1.35e-16  0.00e+00
#> [5,] -0.463  0.530  0.0718 -5.00e-16 -0.0181 -0.70688  1.49e-16  0.00e+00
#> [6,] -0.303 -0.287  0.1624 -4.87e-02  0.3618 -0.00925  8.16e-01  8.76e-17
#> [7,] -0.303 -0.287  0.1624 -4.87e-02  0.3618 -0.00925 -4.08e-01 -7.07e-01
#> [8,] -0.303 -0.287  0.1624 -4.87e-02  0.3618 -0.00925 -4.08e-01  7.07e-01

# 특이값 벡터 d의 첫번째와 두번째 값을 이용하여 원래 행렬 구하기
round(x_svd$u[,c(1,2)] %*% diag(x_svd$d[c(1,2)]) %*% t(x_svd$v[,c(1,2)]))
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#>  [1,]    0    0    0    1    1    0    0    0
#>  [2,]    0    0    0    1    1    0    0    0
#>  [3,]    0    0    0    1    1    0    0    0
#>  [4,]    1    1    1    1    1    1    1    1
#>  [5,]    1    1    1    1    1    1    1    1
#>  [6,]    1    1    1    1    1    1    1    1
#>  [7,]    1    1    1    1    1    1    1    1
#>  [8,]    0    0    0    1    1    0    0    0
#>  [9,]    0    0    0    1    1    0    0    0
#> [10,]    0    0    0    1    1    0    0    0

5.2.14 qr()

qr(x)은 행렬 x의 QR 분해결과를 반환합니다. QR분해는 행렬 A를 \(A = QR\)로 분해하는 것입니다. Q는 단위 노름 직교 벡터를 갖는 행렬이고, R은 상삼각행렬입니다.

x <- matrix(c(1,2,3, 2,4,6, 3,3,3), nrow=3)
x_qr <- qr(x)
x_qr
#> $qr
#>        [,1]   [,2]  [,3]
#> [1,] -3.742 -4.811 -7.48
#> [2,]  0.535  1.964  0.00
#> [3,]  0.802  0.989  0.00
#> 
#> $rank
#> [1] 2
#> 
#> $qraux
#> [1] 1.27 1.15 0.00
#> 
#> $pivot
#> [1] 1 3 2
#> 
#> attr(,"class")
#> [1] "qr"

5.2.15 scale()

scale(x, center = TRUE, scale = TRUE)는 행렬이나 벡터 x를 정규화(표준화)한 결과를 반환합니다. 옵션 center는 평균을 의미하며, scale은 표준편차를 의미합니다. x가 벡터일 경우 \(z = (x-u)/\sigma\)를 구해서 반환합니다. center가 FALSE이면 값에서 평균을 빼지 않으며, scale이 FALSE이면 표준편차로 나누지 않습니다.

# 1~9 벡터를 표준화하기 (평균을 빼고 표준편차로 나눔)
(x <- 1:9)
#> [1] 1 2 3 4 5 6 7 8 9
scale(x)
#>         [,1]
#>  [1,] -1.461
#>  [2,] -1.095
#>  [3,] -0.730
#>  [4,] -0.365
#>  [5,]  0.000
#>  [6,]  0.365
#>  [7,]  0.730
#>  [8,]  1.095
#>  [9,]  1.461
#> attr(,"scaled:center")
#> [1] 5
#> attr(,"scaled:scale")
#> [1] 2.74

x가 행렬일 경우에는 열을 기준으로 평균과 표준편차를 구한 후, 열 기준으로 표준화를 합니다.

(x <- matrix(1:9, ncol = 3))
#>      [,1] [,2] [,3]
#> [1,]    1    4    7
#> [2,]    2    5    8
#> [3,]    3    6    9
scale(x)
#>      [,1] [,2] [,3]
#> [1,]   -1   -1   -1
#> [2,]    0    0    0
#> [3,]    1    1    1
#> attr(,"scaled:center")
#> [1] 2 5 8
#> attr(,"scaled:scale")
#> [1] 1 1 1