본문 바로가기
R 프로그래밍/R advance

와이드 포맷과 롱 포맷 간 데이터 변환

by 찐남 2021. 12. 28.
Cookbook for R을 기반으로 하여 작성하였습니다.

 

이번 포스팅에서는

와이드 형식(wide format)에서 긴 형식(long format)으로

데이터를 변환하는 방법에 대해서 알아볼게요.

R에서 사용하는 많은 함수는

데이터가 와이드 형식이 아닌 긴 형식일 것으로 예상을 하고 있어요.

그러나 가끔 넓은 형식의 데이터를 사용하곤 해요.

 

그래서 두 형식 간의 데이터를 변환시키는 방법에 대해서 알고 있어야

각 상황에 맞는 데이터 분석을 할 수 있어요.

 

그럼 데이터 형식을 변환시키는 방법에 대해 알아볼게요.

 


두 형식 간에 변환을 할 수 있는 방법은 크게 아래 2가지예요.

 

1. tidyr 패키지의 gather()와 spread() 함수 사용

2. reshape2 패키지의 melt() 및 dcast() 함수 사용

(※ 참고로 tidyr 패키지는 reshape2 패키지보다 더 새로운 인터페이스 패키지입니다.)

 

 

※ 위의 2가지 이외에 다른 많은 방법들이 있는데,

여기에서 다루지 않고,

소개만 하고 넘어갈게요.

첫 번째는 reshape() 함수예요.

혼란스러울 수 있는데,

이것은 reshape2 패키지의 일부가 아닌

R에 기본적으로 설치되어 있는 함수예요.

두 번째는 stack()와 unstack() 함수입니다.

 


 

연습 데이터 생성

 

아래 2개의 데이터 프레임은 동일한 데이터를 보유하고 있지만,

와이드 및 롱 형식으로 데이터 표현방식이 다를 뿐이에요.

 

우선 와이드 형식의 데이터 프레임을 생성해 볼게요.

# 와이드(wide) 형식의 데이터 프레임 생성
olddata_wide <- read.table(header=TRUE, text='
subject sex control cond1 cond2
1 M 7.9 12.3 10.7
2 F 6.3 10.6 11.1
3 F 9.5 13.1 13.8
4 M 11.5 13.4 12.9
')

# olddata_wide 데이터에 대한 구조 파악
str(olddata_wide)

olddata_wide는 데이터 프레임이며,

4개의 관측치와 5개의 변수로 구성되어 있다는 것을 알 수 있어요.

subject 변수가 수치형 변수로 되어 있는데,

이후 분석을 위해서 factor형으로 변환할게요.

 

# subject 변수를 factor형으로 변환
olddata_wide$subject <- factor(olddata_wide$subject)

# 변환 후 olddata_wide 데이터에 대한 구조 파악
str(olddata_wide)

subject에 대한 변수형이 4개의 수준을 가지는 factor형으로 변환되었음을 확인할 수 있어요.

 

 

다음은 롱 형식의 데이터 프레임을 생성해 볼게요.

# 롱(long) 형식의 데이터 프레임 생성
olddata_long <- read.table(header=TRUE, text='
subject sex condition measurement
1 M control 7.9
1 M cond1 12.3
1 M cond2 10.7
2 F control 6.3
2 F cond1 10.6
2 F cond2 11.1
3 F control 9.5
3 F cond1 13.1
3 F cond2 13.8
4 M control 11.5
4 M cond1 13.4
4 M cond2 12.9
')

# olddata_long 데이터에 대한 구조 파악
str(olddata_long)

olddata_long 은 데이터 프레임이며,

12개의 관측치와 4개의 변수로 구성되어 있다는 것을 알 수 있어요.

subject 변수가 수치형 변수로 되어 있는데,

이후 분석을 위해서 factor형으로 변환할게요.

 

# subject 변수를 factor형으로 변환
olddata_long$subject <- factor(olddata_long$subject)

# 변환 후 olddata_long데이터에 대한 구조 파악
str(olddata_long)

subject에 대한 변수형이 4개의 수준을 가지는 factor형으로 변환되었음을 확인할 수 있어요.

 


tidyr 패키지를 활용한 데이터 프레임 형식 변환

<와이드 형식에서 롱 형식으로의 변환: gather() 함수 사용>

 

olddata_wide

install.packages('tidyr') # tidyr 패키지 설치
library(tidyr) # tidyr 패키지 로딩

# gather() 함수의 주요 인수:
# - data: Data object
# - key: 데이터 열의 이름으로 만들어진 새로운 키(key) 열의 이름
# - value: 새로운 값 열의 이름
# - ...: 값을 포함하는 소스 열의 이름
# - factor_key: 새 키 열을 factor로의 처리 여부

data_long <- gather(data = olddata_wide,
key = condition,
value = measurement,
control:cond2,
factor_key = TRUE)

data_long

이 예에서 수집되는 소스 열은 control:cond2로 지정됐어요.

이는 control과 cond2 사이에 있는 모든 열을 사용한다는 것을 의미해요.

 

이를 수행하는 또 다른 방법은 아래와 같이 열 이름을 개별적으로 지정하는 것입니다.

gather(olddata_wide, condition, measurement, control, cond1, cond2)

 

프로그래밍 방식으로 gather()를 사용해야 하는 경우, 열 이름이 포함된 변수를 사용해야 할 수도 있어요.

keycol <- "condition"
valuecol <- "measurement"
gathercols <- c("control","cond1","cond2")

gather(olddata_wide,keycol,valuecol,gathercols)

 

변수 열의 factor level의 이름을 바꾸고 정렬할 수도 있어요.

# factor 이름 변경하기 (cond1 -> first) 
levels(data_long$condition)[levels(data_long$condition)=="cond1"] <- "first" 

# factor 이름 변경하기 (cond2 -> second) 
levels(data_long$condition)[levels(data_long$condition)=="cond2"] <- "second" 

# 정렬하기 (첫 번째 정렬 키: subject / 두 번째 정렬 키: condition)
data_long <- data_long[order(data_long$subject, data_long$condition), ]
data_long

 

<롱 형식에서 와이드 형식으로의 변환: spread() 함수 사용>

olddata_long

library(tidyr)

# spread() 함수 인수
# - data: Data object
# - key: 새로운 열 이름을 포함하는 열 이름
# - value: 값을 포함하는 열 이름

data_wide <- spread(data = olddata_long, key = condition, value = measurement)
data_wide

 

데이터를 더 멋지게 보이게 하는 몇 가지 선택사항이 있어요.

# cond1을 first으로 변경하기
names(data_wide)[names(data_wide)=="cond1"] <- "first"

# cond2를 second으로 변경하기
names(data_wide)[names(data_wide)=="cond2"] <- "second"

# 열을 재 정렬하기
data_wide <- data_wide[, c(1,2,5,3,4)]
data_wide 

factor level의 순서는 열의 순서를 결정합니다.

level 순서는 모양을 변경하기 전에 변경하거나 나중에 열을 다시 정렬할 수 있으니, 참고하세요.

 

 


 

reshape2 패키지를 활용한 데이터 프레임 형식 변환

<와이드 형식에서 롱 형식으로의 변환: melt() 함수 사용>

 

olddata_wide

install.packages('reshape2')  #reshape2 패키지 설치
library(reshape2)  # reshape2 패키지 로드

# id.vars 지정: 유지는 하지만, 분할하지 않을 변수
melt(olddata_wide, id.vars=c("subject", "sex")) 

 

출력을 좀 더 쉽게 작업할 수 있도록 하는 유용한 옵션이 있어요.

data_long<-melt(olddata_wide,

# ID 변수들 - 유지는 하지만, 분할하지 않을 변수
id.vars=c("subject","sex"),

# 소스 열
measure.vars=c("control","cond1","cond2"),

# 원본을 식별할 대상 열의 이름
variable.name="condition",

# 측정 열
value.name="measurement"
)

data_long

measure.vars를 생략하면 Melt는 자동으로 다른 모든 변수를 id.vars로 사용하고,

id.vars를 생략하면 그 반대에 해당합니다.

variable.name을 지정하지 않으면 해당 열의 이름을 "변수"로 지정하고,

value.name을 생략하면 해당 열의 이름을 "측정"으로 지정하게 됩니다.

 

변수 열의 factor level 이름을 바꿀 수 있어요.

# factor 이름 변경하기 (cond1 -> first) 
levels(data_long$condition)[levels(data_long$condition)=="cond1"]<-"first"

# factor 이름 변경하기 (cond2 -> second) 
levels(data_long$condition)[levels(data_long$condition)=="cond2"]<-"second"

# 정렬하기 (첫 번째 정렬 키: subject / 두 번째 정렬 키: condition)
data_long<-data_long[order(data_long$subject,data_long$condition),]
data_long

 

<롱 형식에서 와이드 형식으로의 변환: dcast() 함수 사용>

다음 코드는 dcast를 사용하여 데이터를 재구성하는 경우이고,

이 함수는 데이터 프레임을 위한 것이에요.

배열이나 행렬로 작업하는 경우 acast를 사용하셔야 해요.

olddata_long

library(reshape2)
data_wide<-dcast(olddata_long, subject+sex~condition,value.var="measurement")
data_wide

 

데이터를 더 멋지게 보이게 하는 몇 가지 선택사항이 있어요.

# factor 이름 변경하기 (cond1 -> first) 
names(data_wide)[names(data_wide)=="cond1"] <- "first"

# factor 이름 변경하기 (cond2 -> second) 
names(data_wide)[names(data_wide)=="cond2"] <- "second"

# 정렬하기 (첫 번째 정렬 키: subject / 두 번째 정렬 키: condition)
data_wide <- data_wide[, c(1,2,5,3,4)]
data_wide

factor level의 순서는 열의 순서를 결정합니다.

level 순서는 모양을 변경하기 전에 변경하거나 나중에 열을 다시 정렬할 수 있으니, 참고하세요.

 

반응형

댓글