다차원 배열 : 변환하고 요약하기
다차원 배열 : 변환하고 요약하기
다음의 height
은 학생들의 학교(school
), 성별(gender
), 그리고 키(height
) 정보를 3차원 배열에 담고 있다.
height <-
structure(c(170, 180, 175, 169, 165, 173, 173, 181, 175, 166,
164, 155, 172, 184, 176, 167, 162, 164),
.Dim = c(3L, 2L, 3L),
.Dimnames =
list(c("A", "B", "C"), c("M", "F"), c("1", "2", "3")))
height
## , , 1 ## ## M F ## A 170 169 ## B 180 165 ## C 175 173 ## ## , , 2 ## ## M F ## A 173 166 ## B 181 164 ## C 175 155 ## ## , , 3 ## ## M F ## A 172 167 ## B 184 162 ## C 176 164
차원이 늘어날 수록 우리는 전체 정보를 적절하게 처리하기 힘들어 진다. 이때에는 두 가지 방법을 사용할 수 있다. 첫 번째, 자료를 원하는 형식으로 변형하는 것이고, 두 번째, 자료를 요약하여 차원의 수를 줄이는 것이다.
배열 차원에 이름 붙여주기
본격적으로 들어가기에 앞서 다음과 같이 차원에 이름을 붙여주면 데이터를 보기 편하다.
names(dimnames(height)) = c("school", "gender", "number")
height
## , , number = 1 ## ## gender ## school M F ## A 170 169 ## B 180 165 ## C 175 173 ## ## , , number = 2 ## ## gender ## school M F ## A 173 166 ## B 181 164 ## C 175 155 ## ## , , number = 3 ## ## gender ## school M F ## A 172 167 ## B 184 162 ## C 176 164
차원 재배열하기
위의 출력 결과를 보면 동일한 번호(ex. 1,2,3)의 학생 키를 서로 비교하기 쉽게 되어 있다. 예를 들어 번호 1인 A학교의 남자, 여자 학생의 키는 170, 169이면, B 학교의 남자, 여자 학생의 키는 180, 165이다.
하지만 서로 다른 번호의 학생 키를 비교하기는 상대적으로 어렵다. 예를 들어 A학교의 1번 남자, 여자 학생과 A학교의 2번 남자, 여자 학생의 키를 비교하고 싶다면 어떻게 해야 할까? 두 테이블 사이를 왔다 갔다 하는 수 밖에 없다.
한 가지 대안은 자료를 변형하는 것이다. 행렬을 출력할 때 처음 두 차원이 하나의 테이블 형태로 나타나기 때문에 서로 다른 번호끼리 비교하려면 번호를 처음 두 차원의 하나로 이동시키는 것이다. 예를 들어 번호를 첫 번째 차원으로 옮긴다면,
aperm(height, c(3,2,1))
## , , school = A ## ## gender ## number M F ## 1 170 169 ## 2 173 166 ## 3 172 167 ## ## , , school = B ## ## gender ## number M F ## 1 180 165 ## 2 181 164 ## 3 184 162 ## ## , , school = C ## ## gender ## number M F ## 1 175 173 ## 2 175 155 ## 3 176 164
aperm
함수를 간단하게 이해해보자. 3차원 배열인 height
에서 aperm(height, c(1,2,3))
은 height
와 동일하다. 여기서 만약 첫 번째 차원과 세 번째 차원을 바꾸려면 앞에서와 같이 aperm(height, c(3,2,1))
로 한다. c(1,2,3)
에서 첫 번째와 세 번째 원소를 맞바꾼 것이다.
만약 두 번째 차원과 세 번째 차원을 맞바꾸려면 c(1,3,2)
로 가능하다.
aperm(height, c(1,3,2))
## , , gender = M ## ## number ## school 1 2 3 ## A 170 173 172 ## B 180 181 184 ## C 175 175 176 ## ## , , gender = F ## ## number ## school 1 2 3 ## A 169 166 167 ## B 165 164 162 ## C 173 155 164
여러 차원을 동시에 재배열하고자 할 수도 있다.
h2 <- aperm(height, c(2,3,1))
h2
## , , school = A ## ## number ## gender 1 2 3 ## M 170 173 172 ## F 169 166 167 ## ## , , school = B ## ## number ## gender 1 2 3 ## M 180 181 184 ## F 165 164 162 ## ## , , school = C ## ## number ## gender 1 2 3 ## M 175 175 176 ## F 173 155 164
여기서 h2
의 첫 번째 차원은 height
의 2번째 차원이고, h2
의 두 번째 차원은 height
의 3번째 차원, h2
의 세 번째 차원은 height
의 1번째 차원이 된다.
큰 표로 만들기
배열 출력은 세 번째 이후의 차원에 대해서는 독립된 표로 출력이 되기 때문에 보기 힘들다. 다 차원의 배열을 하나의 큰 테이블로 출력할 순 없을까?
ftable(height, row.vars=c("school", "number"))
## gender M F ## school number ## A 1 170 169 ## 2 173 166 ## 3 172 167 ## B 1 180 165 ## 2 181 164 ## 3 184 162 ## C 1 175 173 ## 2 175 155 ## 3 176 164
ftable()
함수를 활용하면 된다. 만약 차원에 이름이 붙여져 있지 않다면, row.vars=
에 차원의 순번을 적는다. row.vars=
는 행에 나열되는 차원을 나타낸다. 만약 한 행에 같은 번호의 학생을 나열하고 싶다면,
ftable(height, row.vars=3) # 번호는 세 번째 차원
## school A B C ## gender M F M F M F ## number ## 1 170 169 180 165 175 173 ## 2 173 166 181 164 175 155 ## 3 172 167 184 162 176 164
요약하여 차원 줄이기
큰 표로 만들면 서로 분리된 표보다 전체 데이터를 잘 이해할 수 있음이 분명하다. 하지만 때때로 표가 너무 커질 수 있고, 알고자 하는 내용과는 상관없는 차원이 존재할 수 있다.
예를 들어 단지 학교 간의 차이를 알고 싶다고 해보자. height
의 세 차원(학교, 성별, 번호)에서 학교만을 남기고 성별, 번호는 모두 생략할 수 있다면 좋을 것이다.
apply(height, MARGIN=c(1), FUN=mean, na.rm=TRUE)
## A B C ## 169.5000 172.6667 169.6667
apply(height, MARGIN="school", FUN=mean, na.rm=TRUE)
## A B C ## 169.5000 172.6667 169.6667
apply()
함수를 활용하면 간단하다. apply()
에서 MARGIN=
은 남길 차원을 나타낸다. 위에서 첫 번째 또는 school
을 적었다.
만약 학교와 성별만을 남기고 싶다면,
apply(height, MARGIN=c(1,2), FUN=mean)
## gender ## school M F ## A 171.6667 167.3333 ## B 181.6667 163.6667 ## C 175.3333 164.0000
height
에서 학교와 성별만을 남기고 싶다면 그 외의 차원을 어떻게 하나의 숫자로 요약할지에 대해 알려줘야 한다. 예를 들어 위의 표에서 학교 A
, 성별 M
에 해당하는 자료는 번호 1
, 2
, 3
있다.
height['A', 'M', '1']
## [1] 170
height['A', 'M', '2']
## [1] 173
height['A', 'M', '3']
## [1] 172
170
, 173
, 172
가 위의 표에서는 171.6667
로 요약된 것이다. 그리고 요약 방법은 FUN=
으로 명시된다. 171.6667
은 mean(c(170, 1732, 172))
의 결과인 것이다.
여러 차원을 하나의 숫자로 요약할 때에도 동일한 방식으로 작동한다.
데이터 프레임으로 변환하기
dfHeight <- as.data.frame.table(height, responseName = 'height')
dfHeight
## school gender number height ## 1 A M 1 170 ## 2 B M 1 180 ## 3 C M 1 175 ## 4 A F 1 169 ## 5 B F 1 165 ## 6 C F 1 173 ## 7 A M 2 173 ## 8 B M 2 181 ## 9 C M 2 175 ## 10 A F 2 166 ## 11 B F 2 164 ## 12 C F 2 155 ## 13 A M 3 172 ## 14 B M 3 184 ## 15 C M 3 176 ## 16 A F 3 167 ## 17 B F 3 162 ## 18 C F 3 164
다시 배열로 변환하기
library(reshape2)
## ## Attaching package: 'reshape2'
## The following objects are masked from 'package:data.table': ## ## dcast, melt
acast(dfHeight, school ~ gender ~ number, value.var = 'height')
## , , 1 ## ## M F ## A 170 169 ## B 180 165 ## C 175 173 ## ## , , 2 ## ## M F ## A 173 166 ## B 181 164 ## C 175 155 ## ## , , 3 ## ## M F ## A 172 167 ## B 184 162 ## C 176 164
요약/정리
여기서는 R 배열에 대해 차원을 재배열하거나 줄이고, 데이터프레임으로 변환하거나, 데이터 프레임을 다시 배열로 변환하는 방법에 대해 알아 보았습니다.
기능 | 함수 |
---|---|
차원 재배열 | aperm(X, c(1,3,2)) |
큰 표로 출력하기 | ftable(X, row.vars=c(1,3)) |
차원 제거 | apply(X, MARGIN=c(1,2), FUN=) |
데이터 프레임으로 | as.data.frame.table() |
다시 배열로 | reshape2::acast(data=, formula=, fun.aggregate=, value.var=) |
Leave a comment