지난번 포스팅에서는 R data.table의 melt(), dcast() 함수를 사용하여 data.table 자료를 녹여서 넓은 자료를 길게(wide to long) 재구조화 해주는 melt() 함수, 반대로 data.table 자료를 주조하여 긴 자료를 넓게 재구조화 해주는 dcast() 함수를 소개하였습니다. (https://rfriend.tistory.com/575)


이번 포스팅에서는 복수의 칼럼 이름이 특정 패턴을 따르는 여러개의 칼럼을 대상으로 

(1) melt() 함수로 data.table 자료의 칼럼 이름에서 패턴을 찾아 녹여서(melt) 넓은 자료를 길게(wide to long) 재구조화

(2) dcast() 함수로 data.table 자료를 주조(cast)하여 긴 자료를 넓게(long to wide) 재구조화

하는 방법을 소개하겠습니다.




 (1) melt() 함수로 data.table 자료의 칼럼 이름에서 패턴을 찾아 녹여서(melt)

     넓은 자료를 길게 (wide to long) 재구조화 하기


먼저 예제로 사용할 'DT' 라는 이름의 data.table 을 fread() 로 데이터를 빠르게 읽어들여서 만들어보겠습니다. 이번 포스팅의 주제에 맞게 자녀 첫째/둘째/셋째의 출생일(date of birth, dob_child1, dob_child2, dob_child3), 자녀 첫째/둘째/셋째의 성별(gender_child1, gender_child2, gender_child3) 칼럼이 특정 패턴을 가진 복수개의 칼럼으로 만들었습니다.



library(data.table)


## -- melting and casting multiple columns
s2 <- "family_id age_mother dob_child1 dob_child2 dob_child3 gender_child1 gender_child2 gender_child3
1         30 1998-11-26 2000-01-29         NA             1             2            NA
2         27 1996-06-22         NA         NA             2            NA            NA
3         26 2002-07-11 2004-04-05 2007-09-02             2             2             1
4         32 2004-10-10 2009-08-27 2012-07-21             1             1             1
5         29 2000-12-05 2005-02-28         NA             2             1            NA"


DT <- fread(s2)
DT
# family_id age_mother dob_child1 dob_child2 dob_child3 gender_child1 gender_child2 gender_child3
# 1:         1         30 1998-11-26 2000-01-29       <NA>             1             2            NA
# 2:         2         27 1996-06-22       <NA>       <NA>             2            NA            NA
# 3:         3         26 2002-07-11 2004-04-05 2007-09-02             2             2             1
# 4:         4         32 2004-10-10 2009-08-27 2012-07-21             1             1             1
# 5:         5         29 2000-12-05 2005-02-28       <NA>             2             1            NA

str(DT)
# Classes 'data.table' and 'data.frame':    5 obs. of  8 variables:
#   $ family_id    : int  1 2 3 4 5
# $ age_mother   : int  30 27 26 32 29
# $ dob_child1   : IDate, format: "1998-11-26" "1996-06-22" "2002-07-11" "2004-10-10" ...
# $ dob_child2   : IDate, format: "2000-01-29" NA "2004-04-05" "2009-08-27" ...
# $ dob_child3   : IDate, format: NA NA "2007-09-02" "2012-07-21" ...
# $ gender_child1: int  1 2 2 1 2
# $ gender_child2: int  2 NA 2 1 1
# $ gender_child3: int  NA NA 1 1 NA
# - attr(*, ".internal.selfref")=<externalptr>




특정 패턴을 따르는 칼럼 이름을 가진 복수의 칼럼을 녹이는(melt) 방법에는 (a) list에 복수의 칼럼 이름을 직접 입력해주는 방법과, (b) 특정 패턴을 정규 표현식(regular expression)으로 매칭하는 2가지가 있습니다.


이때 data.table의 melt(), dcast() 함수는 전부 C 언어로 구현이 되어 있으므로 매우 빠르고 메모리 효율적으로 작동합니다.


(1-a) melt() 함수의 measure 매개변수에 복수의 칼럼 이름을 list()로 넣고, 공통의 value.name 을 지정해서 data.table 넓은 자료를 길게(wide to long) 녹이기 (melt)



## a) Enhanced melt to multiple columns simultaneously.
## The functionality is implemented entirely in C,
## and is therefore both fast and memory efficient in addition to being straightforward.
colA <- paste("dob_child", 1:3, sep="")
colB <- paste("gender_child", 1:3, sep="")


colA
# [1] "dob_child1" "dob_child2" "dob_child3"

colB
# [1] "gender_child1" "gender_child2" "gender_child3"

## We pass a list of columns to 'measure.vars', where each element
## of the list contains the columns that should be combined together.
DT.m2 <- melt(DT,
              measure = list(colA, colB),
              value.name = c("dob", "gender"))
DT.m2
# family_id age_mother variable        dob gender
# 1:         1         30        1 1998-11-26      1
# 2:         2         27        1 1996-06-22      2
# 3:         3         26        1 2002-07-11      2
# 4:         4         32        1 2004-10-10      1
# 5:         5         29        1 2000-12-05      2
# 6:         1         30        2 2000-01-29      2
# 7:         2         27        2       <NA>     NA
# 8:         3         26        2 2004-04-05      2
# 9:         4         32        2 2009-08-27      1
# 10:         5         29        2 2005-02-28      1
# 11:         1         30        3       <NA>     NA
# 12:         2         27        3       <NA>     NA
# 13:         3         26        3 2007-09-02      1
# 14:         4         32        3 2012-07-21      1
# 15:         5         29        3       <NA>     NA

str(DT.m2)
# Classes 'data.table' and 'data.frame':    15 obs. of  5 variables:
#   $ family_id : int  1 2 3 4 5 1 2 3 4 5 ...
# $ age_mother: int  30 27 26 32 29 30 27 26 32 29 ...
# $ variable  : Factor w/ 3 levels "1","2","3": 1 1 1 1 1 2 2 2 2 2 ...
# $ dob       : IDate, format: "1998-11-26" "1996-06-22" "2002-07-11" "2004-10-10" ...
# $ gender    : int  1 2 2 1 2 2 NA 2 1 1 ...
# - attr(*, ".internal.selfref")=<externalptr>



(1-b) melt() 함수의 measure 매개변수에 특정 패턴을 정규 표현식(regular expression)으로 매칭하여 여러개의 칼럼을 녹여서 data.table 넓은 자료를 길게 녹이기 (melt)



## Using patterns()
DT.m2 <- melt(DT,
              # using regular expression
              measure = patterns("^dob", "^gender"),
              value.name = c("dob", "gender"))

DT.m2

# family_id age_mother variable        dob gender
# 1:         1         30        1 1998-11-26      1
# 2:         2         27        1 1996-06-22      2
# 3:         3         26        1 2002-07-11      2
# 4:         4         32        1 2004-10-10      1
# 5:         5         29        1 2000-12-05      2
# 6:         1         30        2 2000-01-29      2
# 7:         2         27        2       <NA>     NA
# 8:         3         26        2 2004-04-05      2
# 9:         4         32        2 2009-08-27      1
# 10:         5         29        2 2005-02-28      1
# 11:         1         30        3       <NA>     NA
# 12:         2         27        3       <NA>     NA
# 13:         3         26        3 2007-09-02      1
# 14:         4         32        3 2012-07-21      1
# 15:         5         29        3       <NA>     NA

 




(2) dcast() 함수로 data.table 자료의 여러개의 칼럼 이름을 주조(cast)하여

     긴 자료를 넓게 (long to wide) 재구조화 하기



## b) Enhanced dcast : casting multiple value.vars simultaneously
## we can provide multiple 'value.var' columns to dcast for data.tables directly
## Everything is taken care of internally, and efficiently. fast and memory efficient.
DT.c2 <- dcast(DT.m2,
               family_id + age_mother ~ variable,
               value.var = c("dob", "gender"))


DT.c2

# family_id age_mother      dob_1      dob_2      dob_3 gender_1 gender_2 gender_3
# 1:         1         30 1998-11-26 2000-01-29       <NA>        1        2       NA
# 2:         2         27 1996-06-22       <NA>       <NA>        2       NA       NA
# 3:         3         26 2002-07-11 2004-04-05 2007-09-02        2        2        1
# 4:         4         32 2004-10-10 2009-08-27 2012-07-21        1        1        1
# 5:         5         29 2000-12-05 2005-02-28       <NA>        2        1       NA

 



[Reference]

* R data.table vignette
: https://cran.r-project.org/web/packages/data.table/vignettes/datatable-reshape.html



이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!



728x90
반응형
Posted by Rfriend
,