재현가능한 과학적 분석을 위한 중급 R

reshape2

학습 목표

  • 그룹 집단으로 칼럼을 쪼개 다수 칼럼을 생성하는 방법을 익힌다.
  • 다수 칼럼을 조합해서 다른 그룹집단으로 된 단일 칼럼을 생성하는 방법을 익힌다.

지금까지 gapminder 데이터셋으로 작업했다:

library("data.table")
gap <- fread("data/gapminder-FiveYearData.csv")
gap
##           country year      pop continent lifeExp gdpPercap
##    1: Afghanistan 1952  8425333      Asia  28.801  779.4453
##    2: Afghanistan 1957  9240934      Asia  30.332  820.8530
##    3: Afghanistan 1962 10267083      Asia  31.997  853.1007
##    4: Afghanistan 1967 11537966      Asia  34.020  836.1971
##    5: Afghanistan 1972 13079460      Asia  36.088  739.9811
##   ---                                                      
## 1700:    Zimbabwe 1987  9216418    Africa  62.351  706.1573
## 1701:    Zimbabwe 1992 10704340    Africa  60.377  693.4208
## 1702:    Zimbabwe 1997 11404948    Africa  46.809  792.4500
## 1703:    Zimbabwe 2002 11926563    Africa  39.989  672.0386
## 1704:    Zimbabwe 2007 12311143    Africa  43.487  469.7093

이런 데이터셋 형식을 “long” 형식이라 부른다: 각 변수가 자체 칼럼을 갖고 있고, 식별 정보를 갖는 칼럼이 다수 있다.

R을 사용해서 신속한 분석에 편리한 데이터 형식이다: data.table을 사용해서 쿼리하고, 필터하고, 데이터를 솜씨있게 조작하기 편리하고, ggplot2에서 그래프 도식화로 기대하는 자료 형식이다.

하지만, 데이터가 이런 형식이 아닌 경우가 있다. 종종 데이터가 “wide” 형식으로 알려진 형태로 주어진 경우가 있다: 변수가 각 집단별로 다수 칼럼으로 쪼개질 수 있다. 또다른 버젼 gapminder 데이터로 불러오자:

# This is an example where `fread` doesn't work: it loses the column names!
gapWide <- as.data.table(read.csv("data/gapminder-wide-format.csv", header=TRUE))
gapWide
##      continent        country pop.1952 pop.1957 pop.1962 pop.1967 pop.1972
##   1:    Africa        Algeria  9279525 10270856 11000948 12760499 14760787
##   2:    Africa         Angola  4232095  4561361  4826015  5247469  5894858
##   3:    Africa          Benin  1738315  1925173  2151895  2427334  2761407
##   4:    Africa       Botswana   442308   474639   512764   553541   619351
##   5:    Africa   Burkina Faso  4469979  4713416  4919632  5127935  5433886
##  ---                                                                      
## 138:    Europe    Switzerland  4815000  5126000  5666000  6063000  6401400
## 139:    Europe         Turkey 22235677 25670939 29788695 33411317 37492953
## 140:    Europe United Kingdom 50430000 51430000 53292000 54959000 56079000
## 141:   Oceania      Australia  8691212  9712569 10794968 11872264 13177000
## 142:   Oceania    New Zealand  1994794  2229407  2488550  2728150  2929100
##      pop.1977 pop.1982 pop.1987 pop.1992 pop.1997 pop.2002 pop.2007
##   1: 17152804 20033753 23254956 26298373 29072015 31287142 33333216
##   2:  6162675  7016384  7874230  8735988  9875024 10866106 12420476
##   3:  3168267  3641603  4243788  4981671  6066080  7026113  8078314
##   4:   781472   970347  1151184  1342614  1536536  1630347  1639131
##   5:  5889574  6634596  7586551  8878303 10352843 12251209 14326203
##  ---                                                               
## 138:  6316424  6468126  6649942  6995447  7193761  7361757  7554661
## 139: 42404033 47328791 52881328 58179144 63047647 67308928 71158647
## 140: 56179000 56339704 56981620 57866349 58808266 59912431 60776238
## 141: 14074100 15184200 16257249 17481977 18565243 19546792 20434176
## 142:  3164900  3210650  3317166  3437674  3676187  3908037  4115771
##      lifeExp.1952 lifeExp.1957 lifeExp.1962 lifeExp.1967 lifeExp.1972
##   1:       43.077       45.685       48.303       51.407       54.518
##   2:       30.015       31.999       34.000       35.985       37.928
##   3:       38.223       40.358       42.618       44.885       47.014
##   4:       47.622       49.618       51.520       53.298       56.024
##   5:       31.975       34.906       37.814       40.697       43.591
##  ---                                                                 
## 138:       69.620       70.560       71.320       72.770       73.780
## 139:       43.585       48.079       52.098       54.336       57.005
## 140:       69.180       70.420       70.760       71.360       72.010
## 141:       69.120       70.330       70.930       71.100       71.930
## 142:       69.390       70.260       71.240       71.520       71.890
##      lifeExp.1977 lifeExp.1982 lifeExp.1987 lifeExp.1992 lifeExp.1997
##   1:       58.014       61.368       65.799       67.744       69.152
##   2:       39.483       39.942       39.906       40.647       40.963
##   3:       49.190       50.904       52.337       53.919       54.777
##   4:       59.319       61.484       63.622       62.745       52.556
##   5:       46.137       48.122       49.557       50.260       50.324
##  ---                                                                 
## 138:       75.390       76.210       77.410       78.030       79.370
## 139:       59.507       61.036       63.108       66.146       68.835
## 140:       72.760       74.040       75.007       76.420       77.218
## 141:       73.490       74.740       76.320       77.560       78.830
## 142:       72.220       73.840       74.320       76.330       77.550
##      lifeExp.2002 lifeExp.2007 gdpPercap.1952 gdpPercap.1957
##   1:       70.994       72.301      2449.0082      3013.9760
##   2:       41.003       42.731      3520.6103      3827.9405
##   3:       54.406       56.728      1062.7522       959.6011
##   4:       46.634       50.728       851.2411       918.2325
##   5:       50.650       52.295       543.2552       617.1835
##  ---                                                        
## 138:       80.620       81.701     14734.2327     17909.4897
## 139:       70.845       71.777      1969.1010      2218.7543
## 140:       78.471       79.425      9979.5085     11283.1779
## 141:       80.370       81.235     10039.5956     10949.6496
## 142:       79.110       80.204     10556.5757     12247.3953
##      gdpPercap.1962 gdpPercap.1967 gdpPercap.1972 gdpPercap.1977
##   1:      2550.8169      3246.9918       4182.664       4910.417
##   2:      4269.2767      5522.7764       5473.288       3008.647
##   3:       949.4991      1035.8314       1085.797       1029.161
##   4:       983.6540      1214.7093       2263.611       3214.858
##   5:       722.5120       794.8266        854.736        743.387
##  ---                                                            
## 138:     20431.0927     22966.1443      27195.113      26982.291
## 139:      2322.8699      2826.3564       3450.696       4269.122
## 140:     12477.1771     14142.8509      15895.116      17428.748
## 141:     12217.2269     14526.1246      16788.629      18334.198
## 142:     13175.6780     14463.9189      16046.037      16233.718
##      gdpPercap.1982 gdpPercap.1987 gdpPercap.1992 gdpPercap.1997
##   1:      5745.1602      5681.3585      5023.2166       4797.295
##   2:      2756.9537      2430.2083      2627.8457       2277.141
##   3:      1277.8976      1225.8560      1191.2077       1232.975
##   4:      4551.1421      6205.8839      7954.1116       8647.142
##   5:       807.1986       912.0631       931.7528        946.295
##  ---                                                            
## 138:     28397.7151     30281.7046     31871.5303      32135.323
## 139:      4241.3563      5089.0437      5678.3483       6601.430
## 140:     18232.4245     21664.7877     22705.0925      26074.531
## 141:     19477.0093     21888.8890     23424.7668      26997.937
## 142:     17632.4104     19007.1913     18363.3249      21050.414
##      gdpPercap.2002 gdpPercap.2007
##   1:       5288.040       6223.367
##   2:       2773.287       4797.231
##   3:       1372.878       1441.285
##   4:      11003.605      12569.852
##   5:       1037.645       1217.033
##  ---                              
## 138:      34480.958      37506.419
## 139:       6508.086       8458.276
## 140:      29478.999      33203.261
## 141:      30687.755      34435.367
## 142:      23189.801      25185.009

상기 데이터테이블은 정확하게 같다. 하지만, 변수 세개 “gdpPercap”, “pop”, “lifeExp”는 데이터를 수집한 각 년도마다 칼럼이 하나다. 이런 형식이 그룹별 속성을 계산할 때 유용하다: 예를 들어 그룹간 상관구조. 엑셀같은 응용프로그램에서 데이터 수집하시는 분이 자료를 구조화하는 더 자연스러운 방식이기도 하다.

“wide”에서 “long” 형식으로 자료를 변환하는 기술은 향후 상당한 시간을 절약할 수 있게 많은 도움이 된다. reshape2 팩키지를 사용해서 해당 작업을 수행한다.

칼럼 결합하기

다수 칼럼을 단일 칼럼으로 접는데, melt 함수를 사용한다:

library(reshape2)
## 
## Attaching package: 'reshape2'
## The following objects are masked from 'package:data.table':
## 
##     dcast, melt
gapLong <- melt(
  data=gapWide,
  id.vars=c("continent", "country") # All other columns will be collapsed into one
)
## Warning in melt.data.table(data = gapWide, id.vars = c("continent",
## "country")): 'measure.vars' [pop.1952, pop.1957, pop.1962, pop.1967, pop.
## 1972, pop.1977, pop.1982, pop.1987, pop.1992, pop.1997, pop.2002, pop.
## 2007, lifeExp.1952, lifeExp.1957, lifeExp.1962, lifeExp.1967, lifeExp.
## 1972, lifeExp.1977, lifeExp.1982, lifeExp.1987, lifeExp.1992, lifeExp.1997,
## lifeExp.2002, lifeExp.2007, gdpPercap.1952, gdpPercap.1957, gdpPercap.1962,
## gdpPercap.1967, gdpPercap.1972, gdpPercap.1977, gdpPercap.1982, gdpPercap.
## 1987, gdpPercap.1992, gdpPercap.1997, gdpPercap.2002, gdpPercap.2007] are
## not all of the same type. By order of hierarchy, the molten data value
## column will be of type 'double'. All measure variables not of type 'double'
## will be coerced to. Check DETAILS in ?melt.data.table for more on coercion.

경고 메시지를 얻는데, pop 칼럼은 ‘정수형’(즉, 자연수), gdpPercaplifeExp 칼럼은 ‘실수형’ 자료형이기 때문이다.

melt 함수가 테이블을 너무나도 많이 접었다. 다른 형태 변수를 본인에 맞는 칼럼으로 구분할 필요가 있다. 먼저, 변수명을 “var”과 “year”로 쪼갠다:

gapLong[, c("var", "year") := colsplit(variable, "\\.", c("var", "year"))]

상기 명령어를 나눠서 살펴보자.

먼저, colsplit(variable, "\\.", c("var", "year")) 명령어는 variable 칼럼을 “var”, “year”으로 칼럼으로 두개 생성한다. 구분자로 .을 사용해서 각 값을 쪼갠다. 구체적 패턴으로 \\.을 사용한다. .은 그 자체로 와일드카드 문자다: 문자열에 모든 문자를 매칭한다.

다음으로, gapLong 데이터테이블에 컬럼 두개를 := 연산자를 사용해서 생성한다. 칼럼을 다수 생성하려면, := 연산자 왼편에 벡터로 명칭을 명세한다.

상기 작업이 잘 동작하기 때문에, variable 칼럼이 필요없어져 삭제한다:

gapLong[,variable := NULL]

마지막으로, value 칼럼을 그룹 집단으로 쪼개서 var 변수에 저장하려고, dcast 함수를 사용한다. 결과를 데이터테이블로 저장하려고, data.table 팩키지에서 메쏘드를 명시적으로 호출한다:

gapLong <- dcast.data.table(
  data=gapLong,  
  # unique identifier columns go to the left of the '~', separated by '+' signs.
  # The grouping column goes to the right of the '~'.
  formula=continent+country+year~var,
  # which column stores the values to be spread over the new columns
  value.var="value" 
)

long 데이터에서 출발한 처음으로 다시 되돌아 왔다!

데이터 형식을 바꾸는 가장 간단한 사례를 살펴봤다. 복합한 경우는 meltdcast 함수를 여러 단계에 걸쳐 사용하고, 결과를 rbind 해서 결합한다.

이런 유형의 작업에 유용한 다른 팩키지는 tidyrsplitstackshape이 있다.