728x90
반응형
지금까지 행렬 생성과 행렬에 대한 기본적인 조작, 데이터 접근, 행렬 연산 등에 대해 학습해 보았다.
이번에는 포스트에선 역행렬, 가운데 행렬과 같은 약간 독특한 행렬들에 대해 학습해보자.
역행렬(Inverse Matrix)
- 역행렬은 행렬의 역수라고 할 수 있으며, 행렬 A와 곱했을 때 단위 행렬 E가 나오게 하는 행렬을 A의 역행렬이라고 한다.
- 역행렬은 정방행렬(n x n)에 대해서만 구할 수 있다. 장방행렬(n x m)에 대해서는 구할 수 없다.
- solve()
: 수식 A %*% X = B에서 X인 행렬을 구한다. 즉, A와 행렬곱 하여 B가 만들어지게 하는 행렬 X를 구한다. - 주요 Parameter
: solve(A, B, ...)
B의 자리를 공란으로 넣는다면, A의 역행렬을 구한다.
vt3 = c(4, 2, 3, 0, 1, 0, 2, 3, 0, 2, 1, 4, 0, 2, 1, 3)
mat3 = matrix(vt3, nrow = 4, byrow = TRUE)
mat3
## [,1] [,2] [,3] [,4]
## [1,] 4 2 3 0
## [2,] 1 0 2 3
## [3,] 0 2 1 4
## [4,] 0 2 1 3
solve(mat3)
## [,1] [,2] [,3] [,4]
## [1,] 0.33333333 -0.3333333 2.00 -2.3333333
## [2,] 0.08333333 -0.3333333 -0.25 0.6666667
## [3,] -0.16666667 0.6666667 -2.50 2.6666667
## [4,] 0.00000000 0.0000000 1.00 -1.0000000
전치행렬(Transpose Matrix)
- R(기초) 행렬(Matrix)(2부)에서 잠깐 다뤘던 전치행렬에 대해서 다시 한번 정리하겠다.
- m*n 행렬의 행과 열을 서로 바꾼 n*m 행렬로 만든 것을 전치 행렬이라고 한다.
- 주대각선(Main Diagonal)을 기준으로 하여 뒤집은 것을 가리킨다.
※ (1,1), (2,2), (3,3).... 과 같이 행과 열의 값이 같은 행렬의 가운데 부분을 주대각선(대각성분)이라 한다. - t()
: 전치행렬로 만든다.
※ 대각성분(주대각선)인 (1,1), (2,2), (3,3)을 기준으로 뒤집은 것이 전치 행렬이다.
mat <- matrix(c(1:12), nrow = 4, byrow = TRUE)
mat
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
## [4,] 10 11 12
t(mat)
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
대칭행렬(Symmetric Matrix)
- 대각성분을 중심으로 대칭인 정방행렬(n*n)을 가리킨다.
- 대각성분을 중심으로 대칭이므로, 원래 행렬과 전치행렬은 동일하다.
- 대칭행렬을 만들고 싶다면, 일반 행렬을 생성하고, 상삼각행렬 혹은 하삼각행렬의 위치에 대하여, 그 전치행렬의 값을 덮어 씌우면 된다.
(무슨 말인지 모르겠지만, 실습을 하며 천천히 따라와보면 이해하게 될 것이다.)
# 대칭행렬을 만들어보자
mat = matrix(c(1:16), nrow = 4, byrow = TRUE)
mat
## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## [2,] 5 6 7 8
## [3,] 9 10 11 12
## [4,] 13 14 15 16
- c(1:16)으로 1~16까지 값이 들어간 벡터로, 정방행렬(4*4)을 만들었다.
# 하삼각행렬의 값들을 가져와보자
lower.tri(mat, diag = FALSE)
## [,1] [,2] [,3] [,4]
## [1,] FALSE FALSE FALSE FALSE
## [2,] TRUE FALSE FALSE FALSE
## [3,] TRUE TRUE FALSE FALSE
## [4,] TRUE TRUE TRUE FALSE
- lower.tri()는 하삼각행렬을 만들 때 사용하는 함수로, 뒤에서 다시 한번 다루겠지만, 가운데 성분을 기준으로하여, 아랫쪽을 TRUE로 Masking한다.
(상삼각행렬을 쓰는 경우엔, upper.tri()를 쓰면 되며, 방법은 동일하다.) - lower.tri()의 parameter인 diag는 대각성분을 포함할 것인지 여부이다.
mat[lower.tri(mat, diag = FALSE)]
## [1] 5 9 13 10 14 15
- 벡터, 행렬에서 Indexing을 할 때, 우리는 대괄호를 사용하여 가져왔었는데, 이 대괄호는 TRUE로 Masking된 값들을 가져오는 것이다.
# 전치행렬에 대한 하삼각행렬의 위치의 값을 본 행렬의 하삼각행렬 위치에 넣도록 하자.
mat[lower.tri(mat, diag = FALSE)] <- t(mat)[lower.tri(mat, diag = FALSE)]
mat
## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## [2,] 2 6 7 8
## [3,] 3 7 11 12
## [4,] 4 8 12 16
- 조금 복잡해보이지만, 원리는 되게 단순하다.
- 대칭행렬은 대각성분을 중심으로 대칭인 행렬이고, 전치행렬은 대각성분을 중심으로 반전된 행렬이다.
- 즉, 원래의 행렬의 하삼각행렬(or 상삼각행렬)에 전치행렬의 하삼각행렬(or 상삼각행렬)의 위치의 값을 넣으면, 대칭행렬이 만들어지는 것이다.
- 이를 더 풀어서 써보면 가운데 성분 아래(하삼각행렬의 위치 = TRUE로 Masking 된 곳)에 가운데 성분 위의 값을 가운데 성분을 중심으로 뒤집어서(전치 행렬) 가운데 성분 아래에 그대로 넣었다고 생각하면 된다.
대각 행렬(Diagonal Matrix)
- 대각행렬은 대칭행렬과 비슷해보이지만, 생성 난이도는 보다 쉬운 행렬이다.
- 대각행렬은 정방행렬(n*n)에서 대각성분을 제외한 모든 값이 0인 경우를 말한다.
- diag()
: 행렬의 대각성분을 가지고 오거나, 대각성분에 다른 값을 넣을 수 있게 해주는 함수, diag(Vector)를 하는 경우, 대각행렬이 생성된다. - 항등행렬(Identity Matrix)는 대각성분이 1이고 나머지 원소는 0인 행렬이므로, 대각성분을 모두 1로 생성하면 된다.
# 대각행렬을 만들어보자.
diag(c(1: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
- 가운데 성분을 제외하고 모두 0인 대각행렬을 만들어보았다.
# 대각성분을 가지고 와보자
mat <- matrix(c(1:16), nrow = 4)
mat
## [,1] [,2] [,3] [,4]
## [1,] 1 5 9 13
## [2,] 2 6 10 14
## [3,] 3 7 11 15
## [4,] 4 8 12 16
diag(mat)
## [1] 1 6 11 16
- diag() 함수를 이용하면, 행렬의 대각성분만 벡터로 가지고 올 수 있다.
# 대각성분의 원소를 모두 0으로 만들자
diag(mat) <- 0
mat
## [,1] [,2] [,3] [,4]
## [1,] 0 5 9 13
## [2,] 2 0 10 14
## [3,] 3 7 0 15
## [4,] 4 8 12 0
- 행렬의 대각성분에 스칼라 값을 넣어서 대각성분이 0인 행렬을 만들어보았다.
- 대칭행렬 만들기와 대각성분을 0으로 만들기를 조합하여 코드를 짜면 대칭행렬이면서 대각성분이 0인 행렬을 만들 수 있다.
하삼각행렬(Lower Triangular Matrix)과 상삼각행렬(Upper Triangular Matrix)
- 하삼각행렬은 대각성분을 중심으로, 그 윗 부분이 모두 0인 정방행렬을 말한다.
- 상삼각행렬은 대각성분을 중심으로, 그 아랫 부분이 모두 0인 정방행렬을 말한다.
- lower.tri()
: 행렬의 가운데 성분을 기점으로(가운데 성분 포함 가능), 아랫 부분을 TRUE로 Masking하는 함수 - upper.tri()
: 행렬의 가운데 성분을 기점으로(가운데 성분 포함 가능), 윗 부분을 TRUE로 Masking하는 함수 - 상삼각행렬은 대각성분을 중심으로, 아랫 부분이 0이므로, lower.tri()함수를 이용해 대각성분 아래쪽을 indexing하여 0을 집어넣으면 된다.
- 하삼각행렬은 대각성분을 중심으로, 윗 부분이 0이므로, upper.tri()함수를 이용해 대각성분 위쪽을 indexing하여 0을 집어넣으면 된다.
# 상삼각행렬을 만들어보자.
mat = matrix(c(1:16), 4)
lower.tri(mat, diag = FALSE)
- diag = FALSE 로 Parameter를 부여하여, 가운데 성분은 Masking하지 않도록 하자.
## [,1] [,2] [,3] [,4]
## [1,] FALSE FALSE FALSE FALSE
## [2,] TRUE FALSE FALSE FALSE
## [3,] TRUE TRUE FALSE FALSE
## [4,] TRUE TRUE TRUE FALSE
mat[lower.tri(mat, diag = FALSE)] <- 0
mat
- 선택된 가운데 성분의 아랫부분에 0을 넣어서 상삼각행렬을 만들었다.
## [,1] [,2] [,3] [,4]
## [1,] 1 5 9 13
## [2,] 0 6 10 14
## [3,] 0 0 11 15
## [4,] 0 0 0 16
# 하삼각행렬을 만들어보자.
mat = matrix(c(1:16), 4)
upper.tri(mat, diag = FALSE)
## [,1] [,2] [,3] [,4]
## [1,] FALSE TRUE TRUE TRUE
## [2,] FALSE FALSE TRUE TRUE
## [3,] FALSE FALSE FALSE TRUE
## [4,] FALSE FALSE FALSE FALSE
mat[upper.tri(mat, diag = FALSE)] <- 0
mat
## [,1] [,2] [,3] [,4]
## [1,] 1 0 0 0
## [2,] 2 6 0 0
## [3,] 3 7 11 0
## [4,] 4 8 12 16
자, 지금까지 역행렬, 전치행렬, 대각행렬, 대칭행렬, 상삼각행렬, 하삼각행렬에 대해 알아보았다. 행렬은 이 것보다 훨씬 심도 깊은 분야기 때문에, R의 기초인 데이터 타입 공부에선 기본적으로 알아야하는 부분만 짚고 넘어가도록 하겠다.
다음 포스트에선 배열(Array)에 대해 학습해보도록 하겠다.
728x90
반응형
'R > Basic' 카테고리의 다른 글
R(기초) 데이터프레임(Data Frame)(1부) (0) | 2020.06.21 |
---|---|
R(기초) 배열(Array) (0) | 2020.06.19 |
R(기초) 행렬(Matrix)(2부) (0) | 2020.06.19 |
R(기초) 행렬(Matrix)(1부) (0) | 2020.06.18 |
R(기초) 연산자와 변수 타입 (0) | 2020.06.18 |