2.7 데이터 프레임(data frame)
학습목표(4 주차): 데이터 프레임 클래스에 대해 알아보고, 데이터 프레임을 생성, 병합(merge), 연산에 대한 함수들에 대해 알아본다.
- Excel 스프레드시트와 같은 형태
이름 | 직장 | 나이 |
---|---|---|
김어준 | 딴지일보 | 51 |
주진우 | 시사인 | 46 |
김용민 | 프리랜서 | 45 |
정봉주 | 정당인 | 59 |
- 데이터 프레임은 데이터 유형에 상관없이 2차원 형태의 데이터 구조
- 행렬과 리스트를 혼합한 자료 형태 \(\rightarrow\) 동일한 길이의 벡터로 이루어진 리스트를 구성요소로 갖는 리스트
- 행렬과 유사한 구조를 갖고 있지만 각기 다른 유형의 자료형태로 자료행렬을 구성할 수 있다는 점에서 행렬과 차이를 갖음
- 행렬과 마찬가지로 변수(열)의 길이(행의 개수)는 모두 동일해야 함
- R에서 가장 빈번하게 활용되고 있는 데이터 클래스임
- 데이터 프레임의 각 열(컬럼)은 벡터로 간주
2.7.1 데이터 프레임 생성
- 데이터 프레임 생성 함수:
data.frame()
data.frame(
# 값 또는 이름(tag) = 값
...,
# 논리값.
# 변수명(열 이름)이 구문 상 유효한 변수인지 또는 중복이 있는지 확인
check.names,
# 논리값. 문자형 벡터의 factor 형 강제 변환 여부
stringsAsFactors,
)
- 데이터 프레임 생성 예시: 모 병원에서 얻은 환자의 인구학적 정보
id <- c(1:10)
sex <- rep(c("Female", "Male"), each = 5)
age <- c(34, 22, 54, 43, 44, 39, 38, 28, 31, 42)
sbp <- c(112, 118, 132, 128, 128, 124, 121, 119, 124, 109)
height <- c(165, 158, 161, 160, 168, 172, 175, 182, 168, 162)
weight <- c(52, 48, 59, 60, 48, 72, 73, 82, 64, 60)
df <- data.frame(id, sex, age, sbp, height, weight,
stringsAsFactors = FALSE)
df
$names
[1] "id" "sex" "age" "sbp" "height" "weight"
$class
[1] "data.frame"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10
'data.frame': 10 obs. of 6 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10
$ sex : chr "Female" "Female" "Female" "Female" ...
$ age : num 34 22 54 43 44 39 38 28 31 42
$ sbp : num 112 118 132 128 128 124 121 119 124 109
$ height: num 165 158 161 160 168 172 175 182 168 162
$ weight: num 52 48 59 60 48 72 73 82 64 60
id sex age sbp
Min. : 1.00 Length:10 Min. :22.00 Min. :109.0
1st Qu.: 3.25 Class :character 1st Qu.:31.75 1st Qu.:118.2
Median : 5.50 Mode :character Median :38.50 Median :122.5
Mean : 5.50 Mean :37.50 Mean :121.5
3rd Qu.: 7.75 3rd Qu.:42.75 3rd Qu.:127.0
Max. :10.00 Max. :54.00 Max. :132.0
height weight
Min. :158.0 Min. :48.00
1st Qu.:161.2 1st Qu.:53.75
Median :166.5 Median :60.00
Mean :167.1 Mean :61.80
3rd Qu.:171.0 3rd Qu.:70.00
Max. :182.0 Max. :82.00
# stringsAsFactors = TRUE 인 경우 sex의 summary() 결과
df <- data.frame(id, sex, age, sbp, height, weight,
stringsAsFactors = TRUE)
summary(df)
id sex age sbp height
Min. : 1.00 Female:5 Min. :22.00 Min. :109.0 Min. :158.0
1st Qu.: 3.25 Male :5 1st Qu.:31.75 1st Qu.:118.2 1st Qu.:161.2
Median : 5.50 Median :38.50 Median :122.5 Median :166.5
Mean : 5.50 Mean :37.50 Mean :121.5 Mean :167.1
3rd Qu.: 7.75 3rd Qu.:42.75 3rd Qu.:127.0 3rd Qu.:171.0
Max. :10.00 Max. :54.00 Max. :132.0 Max. :182.0
weight
Min. :48.00
1st Qu.:53.75
Median :60.00
Mean :61.80
3rd Qu.:70.00
Max. :82.00
summary()
함수는 객체의 클래스에 따라 요약 통계량을 출력해주는 함수로 특히 데이터 프레임이 가지고 있는 변수들의 특징을 손쉽게 알아볼 수 있기 때문에 가장 많이 호출되는 함수 중 하나임. 숫자형 벡터에 대해서는 최솟값(minimum), 1/4 분위수(1st quantile), 중앙값(median), 평균(mean), 3/4 분위수(3rd quantile), 최댓값을 출력하고, factor 형 객체에 대해서는 factor의 각 수준 별 빈도를 출력함. 2차원 이상 table()
객체에 적용 시 \(\chi^2\) 검정(독립성 검정) 결과값을 출력함.
- 이미 정의된 데이터 프레임에 데이터를 추가 가능
- 예를 들어
dbp
라는 벡터에 이완기 혈압(diastolic blood pressure) 데이터가 입력되어 있고df
에dbp
변수를 새롭게 추가 시df$dbp <- x
형태로 추가 - 위 형태로 이미 존재하고 있는 변수(열)에 새로운 값 재할당 가능
- 이러한 형태로 문자형 벡터 추가 시 문자형 벡터는 자동으로 factor로 형 변환 되지 않음
- 예를 들어
x <- 1:nrow(df)
dbp <- c(73, 70, 88, 82, 75, 77, 74, 81, 72, 64)
# df에 "dbp" 열을 생성하고 x 값 대입
df$dbp <- x
df
# df에 운동여부 exercyn 라는 변수 추가
# exercyn 는 "Y" 또는 "N" 두 값을 가짐
df$exercyn <- c("Y", "Y", "N", "Y", "N",
"N", "N", "Y", "N", "Y")
str(df)
'data.frame': 10 obs. of 8 variables:
$ id : int 1 2 3 4 5 6 7 8 9 10
$ sex : Factor w/ 2 levels "Female","Male": 1 1 1 1 1 2 2 2 2 2
$ age : num 34 22 54 43 44 39 38 28 31 42
$ sbp : num 112 118 132 128 128 124 121 119 124 109
$ height : num 165 158 161 160 168 172 175 182 168 162
$ weight : num 52 48 59 60 48 72 73 82 64 60
$ dbp : num 73 70 88 82 75 77 74 81 72 64
$ exercyn: chr "Y" "Y" "N" "Y" ...
- 행렬 및 벡터에서 언급 되었던
rownames()
,colnames()
,names()
,dim()
,ncol()/NCOL()
,nrow()/NROW()
함수 적용 가능
[1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
[1] "id" "sex" "age" "sbp" "height" "weight" "dbp"
[8] "exercyn"
[1] "id" "sex" "age" "sbp" "height" "weight" "dbp"
[8] "exercyn"
[1] 10 8
[1] 8
[1] 10
[1] "V1" "V2" "V3" "V4" "V5" "V6" "V7" "V8"
참고: R Markdown에서 데이터 프레임을 손쉽게 html 파일에 출력하는 방법
- R Markdwon의 YAML 부분에 다음과 같이 옵션을 추가하면 별다른 함수 처리 없이 데이터 프레임을 테이블 형태로 html 문서에 붙일 수 있음. 아래 예시에서
output
이후df_print: paged
옵션을 추가 - 옵션 추가 시 들여쓰기(탭 구분)은 YAML 문서의 트리 구조를 표현한 것이기 때문에 꼭 들여쓰기를 정확히 일치시켜야 함
2.7.2 데이터 프레임 접근 및 필터링
접근방법
- 리스트 데이터 접근 방식
[1] 165 158 161 160 168 172 175 182 168 162
[1] 112 118 132 128 128 124 121 119 124 109
[1] Female Female Female Female Female Male Male Male Male Male
Levels: Female Male
NULL
num [1:10] 112 118 132 128 128 124 121 119 124 109
$names
[1] "height"
$row.names
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
$class
[1] "data.frame"
'data.frame': 10 obs. of 1 variable:
$ height: num 165 158 161 160 168 172 175 182 168 162
- 행렬 데이터 접근 방식
[1] 34 22 54 43 44 39 38 28 31 42
필터링
- 벡터, 행렬과 마찬가지로 비교 연산자를 이용해 조건에 맞는 부분 데이터 추출 가능
# %in% 연산자를 이용해 데이터 프레임의 부분 변수 추출
# id, age 열을 제외한 나머지 데이터 프레임 추출
varname_df <- names(df)
df[, !varname_df %in% c("id", "age")]
데이터 프레임 또는 리스트 접근 시 df$col_name
를 사용한다면 매번 데이터 프레임 이름과 $
을 반복하기 때문에 코드가 불필요하게 복잡해짐. R에서는 데이터 프레임 내부의 열 이름을 직접 접근할 수 있도록 도와주는 몇 가지 함수(예: with()
, attach()
등)가 있는데, with()
와 within()
활용법에 대해 간략히 알아봄.
- 위 예제에서 sex 가 Female이고 나이가 40 이상인 데이터 추출한다고 했을 때
with()
함수 사용
within()
함수는with()
와 유사하지만 코드블록({...}
)을 이용해 보다 자유롭게 데이터 수정 및 추가 가능
2.7.3 데이터 프레임 관련 함수
유틸리티 함수
- 보통 데이터 분석은 외부에서 데이터를 읽은 후 특정 객체에 읽어온 데이터를 할당하는데, 이 경우 데이터가 저장된 객체는 대부분은 데이터 프레임 형태임.
- 읽어온 데이터는 보통 많은 행(표본)으로 구성되어 있기 때문에 데이터를 손쉽게 살펴보는 방법이 필요
head()
/tail()
함수
- 객체(벡터, 행렬, 테이블, 데이터 프레임 등)의 처음 또는 끝에서 부터 몇 개의 데이터(
default = 6L
) 를 순차적으로 보여줌
[1] 4177 9
데이터 프레임 결합 및 분리 함수
rbind()
/cbind()
함수
- 행렬에서 사용한
rbind()
/cbind()
를 데이터 프레임에도 적용 가능
a = data.frame(x1 = rep(0,5), x2 = rep("x",5))
b = data.frame(x1 = rep(1,5), x2 = rep("d",5))
c = data.frame(x3 = rep(2,5), x4 = rep("z",5))
d <- list(1, "d")
e <- list(x5 = rep(4, 5), x6 = rep("y", 5))
# rbind()를 이용해 두 데이터 프레임 a-b 합치기
ab <- rbind(a, b)
ab
Error in match.names(clabs, names(xi)): names do not match previous names
merge()
함수
- 두 데이터 프레임을 공통된 값을 기준으로 병합
- Excel의
vlookup()
함수 또는 데이터베이스 SQL 쿼리 중join
과 동일한 역할을 함 cbind()
의 경우는 단순히 열을 합치는 것이지만merge()
는 공통되는 열을 기준으로 두 데이터셋을 병합- 공통된 데이터가 있을 때만 데이터 병합 수행
# merge() 함수 인수
merge(
x, # 병합할 데이터 프레임
y, # 병합할 데이터 프레임
by, # 병합 기준으로 사용할 컬럼 (문자열 벡터)
by.x, # 병합에 사용할 x와 y의 열 이름이 다른 경우
by.y, # by.x와 by.y에 각각 공통 데이터에 해당하는 열 이름 지정
# 둘 다 문자형 스칼라 또는 벡터값 인수로 받음
all, # 논리값 이순
# TRUE인 경우 x, y 중 공통된 값을 갖는 행이 없을 때
# 해당 쪽을 NA를 채워 병합
# 결과적으로 x, y 전체 행이 결과에 포함
all.x, # x,y 중 특정 쪽에 공통된 값이 없더라도 항상
all.y, # 결과에 포함
)
merge()
함수 예시
d1 = data.frame(Name = c("Park", "Hanzo", "Mercy", "Soldier76" ),
country = c("Korea", "Japan", "Swiss", "USA"))
d2 = data.frame(Age = c(19,38,37,56,31),
Name = c("Park", "Hanzo", "Mercy", "Soldier76","Mei" ) )
d1; d2
[1] 4 2
[1] 5 2
split()
함수
- Factor 형에서 언급한
split()
함수를 통해 그룹 별로 데이터 분할 - 분할된 데이터는 리스트에 저장
$Female
id sex age sbp height weight dbp exercyn
a 1 Female 34 112 165 52 73 Y
b 2 Female 22 118 158 48 70 Y
c 3 Female 54 132 161 59 88 N
d 4 Female 43 128 160 60 82 Y
e 5 Female 44 128 168 48 75 N
$Male
id sex age sbp height weight dbp exercyn
f 6 Male 39 124 172 72 77 N
g 7 Male 38 121 175 73 74 N
h 8 Male 28 119 182 82 81 Y
i 9 Male 31 124 168 64 72 N
j 10 Male 42 109 162 60 64 Y
데이터 정렬 함수
sort()
함수
- 데이터(벡터)의 정렬(오름차순 또는 내림차순) 결과 반환
# sort() 함수 인수
sort(
x, # 정렬할 벡터
decreasing, # 논리값, 내림차순 여부
# default = FALSE
na.last # 논리값. 결측 존재 시 NA 값 위치 지정
) # TRUE: 정렬 후 결측은 마지막에 위치
# FALSE: 맨 처음 NA 위치
- 예시
[1] 22 28 31 34 38 39 42 43 44 54
[1] 182 175 172 168 168 165 162 161 160 158
order()
함수
- 데이터 정렬을 위해 순서에 대한 색인 생성 결과 반환
- 데이터 프레임에서 특정 열 기준으로 데이터 정렬 시 주로 사용