R 행렬과 배열

이 글에서는 R의 자료 객체(data objects) 중 행렬에 대해 다뤄보고자 한다.

행렬

  • 행렬은 동일한 유형의 데이터로 구성된, 2차원 이상의 자료 구조를 갖는 객체이다.
  • 행렬은 다음과 같이 만들 수 있다.
    • matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
  • data에는 벡터가 들어간다. nrow, ncol은 행, 열의 수를 지정하는 것.
  • byrow: 기본값은 FALSE이며, TRUE일 경우 ‘열벡터’ 순서로 채운다. 예시를 참고.
  • dimnames: 각 행과 열의 이름 정의

  • 중요한 함수들
    • nrow(): 행의 개수
    • ncol(): 열의 개수
    • dim(): 행렬의 크기
    • length(): 전체 원소 개수
A <- matrix(c(1:9), nrow = 3, ncol = 3)
At <- matrix(c(1:9), nrow = 3, ncol = 3, byrow = TRUE)
A; At
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
## [3,]    7    8    9
B = matrix(1:6, nrow = 2, ncol = 3, byrow = TRUE,
              dimnames = list(c("row1", "row2"), c("col1", "col2", "col3")))
B
##      col1 col2 col3
## row1    1    2    3
## row2    4    5    6


행렬의 연산

  • 원소 대 원소로 계산되는 연산은 다음과 같은 것들이 있다.
    • +, -, *, ==, !=, <, >, <=, >= 등은 원소 대 원소로 계산된다.
    • 특히 R에서 *는 일반적으로 정의되는 행렬곱과는 다르기 때문에 주의 요망.
  • (고등학교에서 배우는) 행렬곱은?
    • %*%로 정의
  • 기타 행렬 연산
    • 전치 행렬(transpose): t()
    • 역행렬: solve()
    • Cross product: crossprod(X, Y) = t(X) %*% Y
    • 대각행렬: diag()


  • 행렬 연산자를 배웠다면, 간단한 선형대수 지식으로 다음 Overdetermined linear system의 least squares solution을 구해볼 수 있다.

\[ \begin{cases} 3x_1+x_2-x_3=-3 \\ x_1+2x_2=-3 \\ x_2+2x_3=8 \\ x_1+x_2-x_3=9 \end{cases} \]

A <- matrix(c(3, 1, 0, 1, 1, 2, 1, 1, -1, 0, 2, -1), nrow = 4, ncol = 3)
b <- c(-3, -3, 8, 9)
lss <- solve((t(A)%*%A)) %*% t(A) %*% b
lss
##      [,1]
## [1,]   -1
## [2,]    2
## [3,]    1


행렬의 인덱싱

  • 부분벡터(subvector)에서 했던 것과 비슷한 것을 행렬에 대해서도 할 수 있다.
A[3,] # 세 번째 행 추출 
## [1] 0 1 2
A[, 2] # 두 번째 열 추출 
## [1] 1 2 1 1
A[1, 1] # (1, 1) 원소 추출 
## [1] 3
A[, 1:3] # 1에서 3번째 열 추출 
##      [,1] [,2] [,3]
## [1,]    3    1   -1
## [2,]    1    2    0
## [3,]    0    1    2
## [4,]    1    1   -1
A[-1, ] # 1번째 행을 제외한 것 모두 추출 
##      [,1] [,2] [,3]
## [1,]    1    2    0
## [2,]    0    1    2
## [3,]    1    1   -1
A[c(TRUE, FALSE, FALSE, TRUE), ]
##      [,1] [,2] [,3]
## [1,]    3    1   -1
## [2,]    1    1   -1

행렬, 벡터의 결합

  • 열 간의 결합: rbind()
  • 행 간의 결합: cbind()
  • 기본적 사용은 직관적이지만 앞에서 배운 인덱싱을 활용해 볼 수 있다.
X <- matrix(1:9, nrow = 3, ncol = 3, byrow = TRUE)
Y <- matrix(11:19, nrow = 3, ncol = 3, byrow = TRUE)
XY1 <- cbind(X[, 1], Y[, 2])
cbind(X, Y) # 행렬 간의 결합도 가능. 
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    2    3   11   12   13
## [2,]    4    5    6   14   15   16
## [3,]    7    8    9   17   18   19
Z <- matrix(1:6, nrow = 2, ncol = 3)
XZ <- cbind(X[, 1], Z); XZ # 경고 메시지 출력 
## Warning in cbind(X[, 1], Z): number of rows of result is not a multiple of
## vector length (arg 1)
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    3    5
## [2,]    4    2    4    6
x = 1:10
is.matrix(cbind(x)) # cbind 함수의 결과는 벡터가 아닌 행렬로 간주
## [1] TRUE