1. Hello, R > 1-2. R 데이터 타입 학습
R 데이터 타입 학습
R에서 사용되는 다양한 데이터형(data type)과 연산 방법에 대해 학습해 보겠습니다. 해당 장의 내용들은 하나하나 세세하게 외우기보다는, "아, 이런 데이터형이 있구나" 정도로 훑어보고 필요할 때마다 다시 찾아보는 것을 추천합니다.
본 커리큘럼은 각각의 데이터형에 대해 간단히 짚고 넘어갑니다. 추가적인 내용(예: 리스트 등)은 다른 자료를 참고하시길 바랍니다.
대입 연산자(할당 연산자) 이용
=
, <-
, ->
<-
은 =
보다 우선적으로 실행된다.# =: 우변 계산 후 좌변에 대입
x = 5252
y = 8282
z = x + y # z에 13534을 할당
x + y = z # Error 발생
# <- / ->
z <- x + y
x + y -> z
if
, while
, for
등은 사용 불가C와 같은 프로그래밍 언어는 변수 선언 시 데이터형(data type)을 함께 지정해야 됩니다. 그러나 R은 변수에 저장되는 값에 따라 데이터형이 자동으로 결정됩니다.
R에서 사용하는 기본 데이터형은 다음과 같습니다.
데이터형 | 종류 |
---|---|
숫자형 | int(정수), num(실수), cplx(복소수) |
문자형 | chr: 따옴표로 묶어 표기 |
범주형 | factor: 레벨에 따라 분류된 형태 (내부적으로 범주는 숫자로 관리됨) |
논리형 | TRUE(T), FALSE(F) : 반드시 대문자를 입력할 것 |
특수 상수 | - NULL: 정의되지 않은 값 - NA: 결측값 - (-)Inf: (음)양의 무한대 - NaN(Not a Number): 0÷0 혹은 Inf÷Inf 등과 같이 연산이 불가능한 값 표기 |
선언된 변수의 데이터형을 확인하는 함수는 다음과 같습니다.
함수 | 설명 |
---|---|
class(x) | R 객체지향 관점에서 x의 데이터형 (추상적인 데이터형) |
typeof(x) | R 언어 자체 관점에서 x 의 데이터형 (메모리에서 다루는 형식) |
is.integer(x) | x가 정수형이면 TRUE, 아니면 FALSE |
is.numeric(x) | x가 실수형이면 TRUE, 아니면 FALSE |
is.complex(x) | x가 복소수형이면 TRUE, 아니면 FALSE |
is.character(x) | x가 문자형이면 TRUE, 아니면 FALSE |
is.na(x) | x가 NA이면 TRUE, 아니면 FALSE : 결측치 확인용으로 자주 쓰인다! |
💡 class(x)
과 typeof(x)
의 차이점
blood.type1 = c('A', 'B', 'O', 'AB') # c() 함수: 여러 개를 묶어 변수에 저장할 때 사용 blood.type2 = factor(blood.type1) # 1. class(x): R 객체지향 관점에서 x의 데이터형 (추상적인 데이터형) class(blood.type1) > "character" class(blood.type2) > "factor" # 2. typeof(x): R 언어 자체 관점에서 x의 데이터형 (메모리에서 다루는 형식) typeof(blood.type1) > "character" typeof(blood.type2) > "integer"
데이터형을 변환해주는 함수는 다음과 같습니다.
함수 | 설명 |
---|---|
as.facotr(x) | 범주형 변환 |
as.integer(x) | 정수형 변환 |
as.numeric(x) | 숫자형 변환 |
as.character(x) | 문자형 변환 |
as.matrix(x) | 행렬 변환 |
as.array(x) | 배열 변환 |
한 가지 주의할 점은, 해당 함수들이 데이터형을 바꾸어 출력만 해준다는 것입니다. 겉모습만 바꿔주는 것이죠. 변수의 데이터형을 변환하고 싶다면 아래처럼 명령어를 입력해야 됩니다.
as.character(blood.type1) # 범주형을 정수형으로 변환하여 출력
class(blood.type1)
> "factor"
blood.type1 = as.character(blood.type1) # 변환된 데이터형으로 저장
class(blood.type1)
> "character"
선언한 변수에 산술, 비교, 논리 등의 다양한 연산자를 사용하면 원하는 데이터를 얻을 수 있습니다. 각각의 연산자를 살펴보겠습니다.
연산자 | 설명 | 예 |
---|---|---|
+ | 덧셈 | 1 + 1 → 2 |
- | 뺄셈 | |
* | 곱셈 | 9 * 9 → 81 |
/ | 나눗셈 | |
^ or ** | 지수승 | 3^3 → 27 |
x %% y | x를 y로 나눈 나머지 | 2 %% 81 → 2 |
x %/% y | x를 y로 나눈 몫 | 2 %/% 81 → 0 |
연산자 | 설명 | 예 |
---|---|---|
< | 미만 | |
<= | 이하 | |
> | 초과 | |
>= | 이상 |
연산자 | 설명 | 예 |
---|---|---|
== | 좌변과 우변이 같다 | |
!= | 좌변과 우변이 다르다 | |
!x | 부정(not) | !TRUE → FALSE |
x | y or x || y | x or y(또는, 합집합) | TRUE | FALSE → TRUE |
x & y or x && y | x and y(그리고, 교집합) | TRUE & FALSE → FALSE |
isTRUE(x) | x의 TRUE 여부 판단 | isTRUE(TRUE) → TRUE isTRUE(FALSE) → FALSE |
지금부터는 하나의 변수가 아닌 여러 개의 변수를 다루는 방법에 대해 살펴보겠습니다.
생성 연산자 사용: 시작값:종료값
# 증가하는 벡터
1:10
> 1 2 3 4 5 6 7 8 9 10
# 감소하는 벡터
10:1
> 10 9 8 7 6 5 4 3 2 1
c()
함수: 일반 벡터 생성
c(5:8)
> 5 6 7 8
c(1, 2, c(5:8))
> 1 2 5 6 7 8
v = c(2, 4, 6) # 변수 v에 저장
> 2 4 6
seq()
함수: 순열 벡터 생성
from
: 초깃값to
: 종료값by
: 증가값seq(from=3, to=10, by=3) # 숫자만 써도 ok
seq(3, 10 ,3)
> 3 6 9
seq(0.1, 1, length.out=10) # length.out: 요소 개수
> 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
rep()
함수: 반복 벡터 생성
times
: 벡터 반복 횟수each
: 요소 반복 횟수rep(c(2:4), times=2) # 벡터 전체를 반복
> 2 3 4 2 3 4
rep(c(2:4), each=3) # 개별 요소를 반복
> 2 2 2 3 3 3 4 4 4
벡터의 개별 요소 값에 접근하거나 출력하는 방법에 대해 살펴보겠습니다. 주의할 점은 다른 프로그래밍 언어와 달리, R의 요소 값 접근은 1부터 시작된다는 것입니다. 잊지 마세요 😉
x = c(1, 2, 3, 4, 5)
length(x)
> 5
단일값 접근
x[1]
> 1 # 다른 프로그래밍 언어와 다르다!
복수 개의 값 접근
x[1, 2, 3]
> Error in x[1, 2, 3] : incorrect number of dimensions
x[c(1, 2, 3)]
> 1 2 3
x[c(1:3)]
> 1 2 3
x[-c(1, 2, 3)] # -: 해당되는 값을 제외한 결과 출력
> 4 5
추가로 벡터의 연산은 다음 경우에만 가능합니다.
아래 벡터들의 연산을 통해 직접 확인해 보시길 바랍니다.
a = c(2, 4, 6, 8)
b = c(1, 3, 5, 7)
p = c(5, 10)
q = c(3, 6, 9)
요소들의 조건 검토
all
: 벡터 내 모든 요소가 조건을 만족하는가any
: 벡터 내 일부 요소가 조건을 만족하는가x = 2:8
all(x>5) # 벡터 내 모든 요소 값이 5보다 큰가?
> FALSE
any(x>5) # 벡터 내 일부 요소 값이 5보다 큰가?
> TRUE
데이터의 일부 요소 추출
데이터 개수를 입력하지 않는 경우, 기본적으로 6개가 추출된다.
head(벡터, 데이터 개수)
: 데이터의 앞부분 일부tail(벡터, 데이터 개수)
: 데이터의 뒷부분 일부x = 2:8
head(x)
> 2 3 4 5 6 7
tail(x)
> 3 4 5 6 7 8
벡터 간 집합 연산
union
: 합집합intersect
: 교집합setdiff
: 차집합setequal
: 두 벡터의 요소가 동일한지 비교한 뒤, T or F로 표시x = c(1, 2, 3)
y = c(2, 4 ,6)
z = c(6, 4, 2)
# 합집합
union(x, y)
> 1 2 3 4 6
# 교집합
intersect(x, y)
> 2
# 차집합
setdiff(x, y)
> 1 3
setdiff(y ,x)
> 4 6
# 요소 비교
setequal(x, y)
> FALSE
setequal(x, z)
> TRUE
벡터를 좀 더 확장해 보겠습니다. 1차원의 벡터를 '행(row)'과 '열(column)'로 구성된 2차원으로 확장시킨 것이 행렬(matrix)이고, n차원으로 확장한 것을 배열(array)이라고 합니다.
행렬과 배열은 엄연히 다르나, 표현의 어색함(행렬식 → 배열식 등)을 피하기 위해 본 교안에서는 둘을 혼용하여 사용하겠습니다.
배열은 기본적으로 열 방향으로 채워집니다.
2차원 배열(행렬) 생성: matrix
x = 1:10
# 행/열 수 지정
matrix(x, nrow = 5) # 행 수 지정: 5x2 행렬
matirx(x, ncol = 5) # 열 수 지정: 2x5 행렬
# 행 단위 데이터 배치여부 결정 → T/F로 표시
matrix(x, nrow = 5, byrow = T) # default: F
# 행/열 이름 목록 추가(list 사용)
matrix(1:12, nrow = 3, byrow = T,
dimnames = list(c('행1', '행2', '행3'), c('열1', '열2', '열3', '열4')))
n차원 배열 생성: array
x = array(1:5, c(2, 4))
# 1:5 → 벡터 데이터
# c(2, 4) → 차원 정의(2x4 행렬)
생성된 배열 | [,1] | [,2] | [,3] | [,4] |
---|---|---|---|---|
[1,] | 1 | 3 | 5 | 2 |
[2,] | 2 | 4 | 1 | 3 |
배열 요소 접근
# 1행 요소 값 출력
x[1, ]
> 1 3 5 2
# 3열 요소 값 출력
x[, 3]
> 5 1
# 특정 위치 요소 값 출력
x[2, 3]
> 1
x[1, 2:4]
> 3 5 2
행/열 단위로 묶어 배열 생성
v1 = c(1, 3, 5, 7)
v2 = c(2, 4, 6, 8)
v3 = c(3, 6, 9, 12)
rbind(벡터1, 벡터2, ...)
: 행 단위로 묶어 배열 생성
[,1] | [,2] | [,3] | [,4] | |
---|---|---|---|---|
v1 | 1 | 3 | 5 | 7 |
v2 | 2 | 4 | 6 | 8 |
v3 | 3 | 6 | 9 | 12 |
cbind(벡터1, 벡터2, ...)
: 열 단위로 묶어 배열 생성
v1 | v2 | v3 | |
---|---|---|---|
[1,] | 1 | 2 | 3 |
[2,] | 3 | 4 | 6 |
[3,] | 5 | 6 | 9 |
[4,] | 7 | 8 | 12 |
연산자 | 설명 |
---|---|
+, - | 행렬의 덧셈, 뺄셈 |
* | R의 행렬 곱셈(각 열별 곱셈) |
%*% | 수학적 행렬 곱셈(내적) |
t(), aperm() | 전치 행렬 |
solve() | 역행렬 |
det() | 행렬식 |
apply(행렬 데이터, 1 혹은 2, 연산 함수)
: 배열의 행/열별로 함수 적용
x = array(1:10, c(2,5))
> 1 3 5 7 9
2 4 6 8 10
# 1: 행별로 함수 적용
apply(x, 1, mean)
> 5 6
# 2: 열별로 함수 적용
apply(x, 2, mean)
> 1.5 3.5 5.5 7.5 9.5
dim(배열)
: 배열의 크기(차원의 수) 출력
x = array(1:10, c(2,5))
> 1 3 5 7 9
2 4 6 8 10
dim(x)
> 2 5
R에서 가장 많이 사용되는 구조인 데이터 프레임(data frame)에 대해 살펴보겠습니다.
data.frame
name = c('코', '사', '다', '마')
age = c(10, 20, 30, 40)
gender = factor(c('M', 'F', 'F', 'M'))
blood.type = factor(c('A', 'B', 'O', 'AB'))
# 데이터 프레임 생성
cosadama = data.frame(name, age, gender, blood.type)
name | age | gender | blood.type | |
---|---|---|---|---|
1 | 코 | 10 | M | A |
2 | 사 | 20 | F | B |
3 | 다 | 30 | F | O |
4 | 마 | 40 | M | AB |
📖 참고하기: 데이터 프레임 간단하게 만드는 방법
edit
테이블 형태의 입력 창에 값을 입력하고 닫으면, 해당 값이 데이터 프레임에 저장된다.
# 직접 확인해보세요 :) cosadama = edit(cosadama) test = data.frame() # 빈 데이터 프레임으로 실습 test = edit(test)
$
: 특정 속성 변수에 접근
각 요소에 접근할 경우, 배열과 마찬가지로 [ ]
를 이용한다.
,(반점)
을 잊지 말 것!cosadama$name
> '코' '사' '다' '마'
# 특정 조건을 충족하는 데이터 추출
cosadama[cosadama$name == '코',] # ,(반점) 잊지 않기
> 코 10 M A
# '코'의 나이와 혈액형만 추출
cosadama[cosadama$name == '코', c('age', 'blood.type')]
> 10 A
본 커리큘럼에서는 na.omit
을 제외한 함수들을 자세히 다루지 않습니다. 가볍게 훑어보시길 바랍니다.
attach(속성명)
: 데이터 프레임의 속성명을 변수로 사용
detach(속성명)
: 변수 사용 해제
subset(데이터 프레임, 조건, select=c('열1, ...'))
: 데이터 프레임에서 일부 데이터만 추출
na.omit
: 결측값(NA)을 가진 행 제외 추출
head(airquality)
head(na.omit(airquality$Ozone)) # Ozone 속성만 결측값 제거
head(na.omit(airquality)$Ozone) # 모든 속성의 결측값 제거
is.data.frame(데이터 프레임)
: 어떤 변수가 데이터 프레임인지 확인 → TRUE, FALSE로 표시as.data.frame(데이터 프레임)
: 어떤 변수를 데이터 프레임으로 변환