R 객체(object)의 종류와 특징
이 글은 2018~2019년에 작성한 R 기반 강의 노트를 옮긴 것입니다. 코드 일부는 현재 패키지 버전과 다를 수 있습니다.
R 객체 이해하기
- R은 변수 대신 객체를 사용합니다.
- 사전에 class를 정의할 필요가 없습니다.
- 대소문자를 구분하며, 영문과 한글, 숫자를 사용할 수 있지만 반드시 문자로 시작해야 합니다.
- 객체에 다른 객체를 할당(assign)하면, 그 객체의 값이 저장됩니다.
- 또한 객체에 사용자 정의 함수(user defined function)를 할당할 수 있습니다.
R 객체의 종류
- 벡터(vector) : 데이터의 집합 (1차원)
- 행렬(matrix) : 행과 열을 가지는 구조 (2차원)
- 배열(array) : 행과 열을 층으로 쌓은 구조 (3차원?)
- 리스트(list) : 객체를 원소로 가지는 객체로 가장 광범위한 형태의 객체
- 데이터프레임(data frame) : 길이가 같은 서로 다른 벡터를 원소로 갖는 객체 (2차원)
- 행렬은 같은 형태의 벡터만 가집니다. (숫자형, 문자형, 복소수형, 논리형, 범주형 등)
- 반면, 데이터프레임은 다른 형태의 벡터를 가질 수 있습니다. (단, 길이가 같아야 함)
- 길이가 서로 다른 벡터의 경우 리스트의 형태로 저장할 수 있습니다.
- 데이터프레임은 SAS 사용자에게 가장 익숙한 형태의 객체입니다.
벡터의 특징
- R 객체 중 가장 기본이 되는 단위입니다.
- 스칼라(scalar value)는 원소가 한 개인 벡터입니다.
- 같은 형태의 스칼라값들로 구성됩니다. (숫자형, 문자형, 복소수형, 논리형, 범주형)
- 다른 형태의 스칼라값들이 섞이면 강제할당(coercion)이 발생합니다.
- logical, factor < integer < numeric < complex < character < list
벡터의 종류
- numeric : 숫자형. integer(정수)와 double(실수)를 포합니다.
- character : 문자형
- complex : 복소수형. 정수와 허수(i) 부분으로 이루어집니다.
- logical : 논리형. 참(TRUE or T)과 거짓(FALSE or F)로 이루어집니다.
- factor : 범주형. 외형적으로는 문자로 보이지만 정수형 벡터입니다. 데이터 분석 시 문자형을 범주형으로 바꿔주어야 할 필요가 있습니다.
# R의 기본단위는 벡터(vector), scalar는 원소가 한 개인 벡터입니다.
a <- 10
print(a)
## [1] 10
class(a)
## [1] "numeric"
mode(a)
## [1] "numeric"
typeof(a)
## [1] "double"
[참고] class, typeof, mode 차이점
- class(object) : R 객체의 관점에서 객체의 형태를 확인할 때 사용합니다.
- class는 함수에 의해 생성되는 객체입니다.
- 만약 특정 class가 지정되지 않으면 mode와 동일한 값을 가집니다.
- typeof(object) : R의 관점에서 객체의 형태를 확인합니다.
- mode(object) : 객체가 메모리에 저장되는 형태를 확인합니다.
# 객체의 속성을 확인하는 사용자 정의 함수를 생성합니다.
# 문자열과 함수값을 한 번에 출력하기 위해 cat() 함수를 사용합니다.
# cat() 함수 안에 "\n"를 추가하면, 강제 줄 바꿈(enter)이 됩니다.
checkClass <- function(obj) {
cat("# class :", class(obj), "\n")
cat("# mode :", mode(obj), "\n")
cat("# typeof :", typeof(obj), "\n")
}
이제부터 다양한 벡터의 종류별 특성을 간단하게 확인해보겠습니다.
# 숫자형 벡터 (numeric)
# 벡터의 요소를 결합하려면 c() 함수를 이용합니다.
# 벡터에 정수를 할당하여도 속성은 numeric을 갖습니다.
# 만약 integer 속성을 갖는 벡터를 생성하려면 숫자 뒤에 대문자L을 붙입니다.
a <- c(1, 3)
print(a)
## [1] 1 3
checkClass(a)
## # class : numeric
## # mode : numeric
## # typeof : double
b <- c(1L, 3L)
print(b)
## [1] 1 3
checkClass(b)
## # class : integer
## # mode : numeric
## # typeof : integer
# 문자형 벡터 (character)
# 문자형 벡터의 요소는 홑따옴표 또는 겹따옴표로 묶인 문자입니다.
# 숫자도 따옴표를 씌우면 문자로 변환됩니다.
c <- c("hello", "world")
print(c)
## [1] "hello" "world"
checkClass(c)
## # class : character
## # mode : character
## # typeof : character
# 복소수형 벡터 (complex)
# 복소소수형 벡터는 실수 부분과 허수 부분의 합으로 되어 있습니다.
# 허수를 의미하는 i에 0을 곱해도 복소수형을 갖습니다.
d <- c(1+3i, 5+10i)
print(d)
## [1] 1+ 3i 5+10i
checkClass(d)
## # class : complex
## # mode : complex
## # typeof : complex
# 논리형 벡터 (logical)
# 논리형 벡터에 사용되는 TRUE와 FALSE는 따옴표 없이 대문자로만 사용됩니다.
# 앞글자만 입력해도 됩니다.
# TRUE는 1, FALSE는 0의 값을 갖습니다.
e <- c(TRUE, FALSE, T, F)
print(e)
## [1] TRUE FALSE TRUE FALSE
checkClass(e)
## # class : logical
## # mode : logical
## # typeof : logical
# 범주형 벡터 (factor)
# 범주형 벡터는 문자같이 출력되지만 정수값을 갖는 숫자형 벡터입니다.
# level 순서대로 1, 2, 3 등의 정수값이 할당됩니다.
f <- factor(c)
print(f)
## [1] hello world
## Levels: hello world
checkClass(f)
## # class : factor
## # mode : numeric
## # typeof : integer
속성이 다른 벡터들을 결합하면 강제할당(coercion)이 발생합니다.
# 먼저 논리형 벡터 g를 생성합니다.
g <- c(FALSE, TRUE)
print(g)
## [1] FALSE TRUE
checkClass(g)
## # class : logical
## # mode : logical
## # typeof : logical
# 논리형 벡터에 범주형 벡터를 결합하니 정수형 벡터로 바뀌었습니다.
g <- c(g, f)
print(g)
## [1] 0 1 1 2
checkClass(g)
## # class : integer
## # mode : numeric
## # typeof : integer
# 정수형 벡터에 정수형 스칼라값을 결합하니 정수형 벡터가 유지되었습니다.
g <- c(g, 3L)
print(g)
## [1] 0 1 1 2 3
checkClass(g)
## # class : integer
## # mode : numeric
## # typeof : integer
# 정수형 벡터에 소수점이 있는 실수 스칼라값을 결합하니 숫자형 벡터로 바뀌었습니다.
# 4.0 대신에 대문자 L이 없는 정수 4를 할당해도 같은 결과를 갖습니다.
g <- c(g, 4.0)
print(g)
## [1] 0 1 1 2 3 4
checkClass(g)
## # class : numeric
## # mode : numeric
## # typeof : double
# 숫자형 벡터에 복소수 스칼라값을 결합하니 모두 복소수형 벡터로 바뀌었습니다.
g <- c(g, 5+0i)
print(g)
## [1] 0+0i 1+0i 1+0i 2+0i 3+0i 4+0i 5+0i
checkClass(g)
## # class : complex
## # mode : complex
## # typeof : complex
# 복소수형 벡터에 문자열 스칼라값을 결합하니 모두 문자형 벡터로 바뀌었습니다.
g <- c(g, "6")
print(g)
## [1] "0+0i" "1+0i" "1+0i" "2+0i" "3+0i" "4+0i" "5+0i" "6"
checkClass(g)
## # class : character
## # mode : character
## # typeof : character
행렬 (Matrix)
- 행과 열로 구성된 2차원의 객체이나 같은 타입의 데이터만 가지므로 데이터프레임에 비해 가볍습니다.
- 행렬 연산 또는 행렬 객체를 요구하는 함수의 경우, 데이터프레임 대신 행렬을 입력해야 합니다.
- 행렬 객체를 생성하려면 matrix() 함수를 이용하면 됩니다.
- matrix() 함수의 주요 인자로는 data, nrow, ncol, byrow 등이 있습니다.
- data 인자에는 행렬로 만들 벡터를 할당합니다.
- nrow 인자에는 행의 수를 할당합니다. 생략하면 벡터의 길이가 자동으로 할당됩니다.
- ncol 인자에는 열의 수를 할당합니다. 생략하면 nrow 값에 의해 자동으로 설정됩니다.
- byrow 인자에는 논리값을 할당합니다. FALSE가 기본값이므로 열 기준으로 벡터가 채워집니다.
# 1부터 10까지의 연속된 정수를 할당하여 행렬을 생성합니다.
# nrow 인자를 지정하지 않았으므로, byrow = FALSE에 따라
# 벡터의 길이(10)만큼의 행을 갖는 행렬이 생성됩니다.
x <- matrix(data = 1:10)
print(x)
## [,1]
## [1,] 1
## [2,] 2
## [3,] 3
## [4,] 4
## [5,] 5
## [6,] 6
## [7,] 7
## [8,] 8
## [9,] 9
## [10,] 10
checkClass(x)
## # class : matrix
## # mode : numeric
## # typeof : integer
# nrow 인자에 1을 할당하면, 1행 10열을 갖는 행렬이 생성됩니다.
x <- matrix(data = 1:10, nrow = 1)
print(x)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 2 3 4 5 6 7 8 9 10
checkClass(x)
## # class : matrix
## # mode : numeric
## # typeof : integer
# nrow 인자에 2를 할당하면, 2행 5열을 갖는 행렬이 생성됩니다.
x <- matrix(data = 1:10, nrow = 2)
print(x)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 3 5 7 9
## [2,] 2 4 6 8 10
checkClass(x)
## # class : matrix
## # mode : numeric
## # typeof : integer
# nrow 인자에 2, ncol 인자에 4를 할당하면, 2행 4열을 갖는 행렬이 생성되고,
# 나머지 숫자(9, 10)는 더이상 사용되지 않습니다.
x <- matrix(data = 1:10, nrow = 2, ncol = 4)
## Warning in matrix(data = 1:10, nrow = 2, ncol = 4): data length [10] is not
## a sub-multiple or multiple of the number of columns [4]
print(x)
## [,1] [,2] [,3] [,4]
## [1,] 1 3 5 7
## [2,] 2 4 6 8
checkClass(x)
## # class : matrix
## # mode : numeric
## # typeof : integer
# byrow 인자에 TRUE(또는 T)를 할당하면 행 기준으로 숫자가 채워집니다.
x <- matrix(data = 1:10, nrow = 2, ncol = 5, byrow = T)
print(x)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
checkClass(x)
## # class : matrix
## # mode : numeric
## # typeof : integer
행렬은 같은 타입의 데이터만 요소로 갖는다고 앞에서 언급하였습니다.
# 문자형 행렬을 생성합니다.
x <- matrix(data = letters[1:10], nrow = 2)
print(x)
## [,1] [,2] [,3] [,4] [,5]
## [1,] "a" "c" "e" "g" "i"
## [2,] "b" "d" "f" "h" "j"
checkClass(x)
## # class : matrix
## # mode : character
## # typeof : character
# 논리형 행렬을 생성합니다.
# rep(T, 5)는 T를 5번 연속으로 반복하라는 명령어입니다.
x <- matrix(data = c(rep(T, 5), rep(F, 5)), nrow = 2, byrow = T)
print(x)
## [,1] [,2] [,3] [,4] [,5]
## [1,] TRUE TRUE TRUE TRUE TRUE
## [2,] FALSE FALSE FALSE FALSE FALSE
checkClass(x)
## # class : matrix
## # mode : logical
## # typeof : logical
배열 (arrary)
- 배열은 2차원 이상의 데이터를 저장할 수 있는 형태입니다.
- 인자(argument) 설정에 따라 2차원 행렬을 여러겹 쌓을 수 있습니다.
- 배열 객체를 생성하려면 array() 함수를 이용합니다.
- array() 함수의 주요 인자로는 data, dim, dimnames 등이 있습니다.
- data 인자에는 배열의 원소가 될 데이터를 할당합니다.
- dim 인자에는 “행, 열, 층” 순서대로 차원수를 설정합니다. 이 때 c() 함수를 이용합니다.
- dimnames 인자에는 “행이름, 열이름, 층이름” 순서대로 차원명을 설정합니다. 이 때 list() 함수를 이용합니다.
# 2개의 행, 3개의 열을 가진 행열을 2개의 층으로 생성합니다.
y <- array(data = 1:6,
dim = c(2, 3, 2),
dimnames = list(c("R1", "R2"),
c("C1", "C2", "C3"),
c("M1", "M2")))
print(y)
## , , M1
##
## C1 C2 C3
## R1 1 3 5
## R2 2 4 6
##
## , , M2
##
## C1 C2 C3
## R1 1 3 5
## R2 2 4 6
checkClass(y)
## # class : array
## # mode : numeric
## # typeof : integer
데이터프레임 (dataframe)
- 데이터프레임은 같은 길이의 서로 다른 벡터들을 열로 가지는 2차원 객체입니다.
- 길이가 다른 벡터들을 원소로 갖는 리스트(list)의 하위 개념이라 할 수 있습니다.
- 외부의 데이터 불러오면 기본적으로 데이터프레임으로 저장됩니다.
- SAS 사용자에게 가장 익숙한 형태의 R 객체이며 데이터분석의 주요 대상입니다.
- 데이터프레임 객체를 생성하려면 data.frame() 함수를 이용합니다.
- 함수 내 컬럼명과 원소로 사용될 벡터를 할당하면 됩니다.
# a, b, c 벡터를 생성하고, d라는 데이터프레임 객체에 원소로 할당합니다.
# 데이터프레임의 각 컬럼은 서로 다른 속성을 가질 수 있지만, 각 열의 길이가 같아야 합니다.
a <- 1:10
b <- letters[1:10]
c <- rep(c(T, F), 5)
d <- data.frame(num = a, cha = b, log = c)
print(d)
## num cha log
## 1 1 a TRUE
## 2 2 b FALSE
## 3 3 c TRUE
## 4 4 d FALSE
## 5 5 e TRUE
## 6 6 f FALSE
## 7 7 g TRUE
## 8 8 h FALSE
## 9 9 i TRUE
## 10 10 j FALSE
checkClass(d)
## # class : data.frame
## # mode : list
## # typeof : list
# 만약 길이가 다르면 에러가 발생합니다. (직접 해보세요)
# a <- 1:10
# b <- letters[1:12]
# c <- rep(c(T, F), 4)
# d <- data.frame(num = a, cha = b, log = c)
리스트 (list)
- R의 객체 중 가장 광범위하게 사용되는 객체입니다.
- 데이터프레임은 모든 컬럼의 길이가 서로 같아야 하지만, 리스트는 같지 않아도 됩니다.
- 리스트는 다양한 데이터 타입을 요소로 갖는 객체이므로 가장 다루기 어려운 객체 중 하나입니다.
# 각 열의 길이가 서로 달라도 에러가 발생하지 않습니다.
a <- 1:8
b <- letters[1:12]
c <- rep(c(T, F), 3)
d <- list(num = a, cha = b, log = c)
print(d)
## $num
## [1] 1 2 3 4 5 6 7 8
##
## $cha
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
##
## $log
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
checkClass(d)
## # class : list
## # mode : list
## # typeof : list