재현가능한 과학적 분석을 위한 중급 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 칼럼은 ‘정수형’(즉, 자연수), gdpPercap과 lifeExp 칼럼은 ‘실수형’ 자료형이기 때문이다.
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 데이터에서 출발한 처음으로 다시 되돌아 왔다!
데이터 형식을 바꾸는 가장 간단한 사례를 살펴봤다. 복합한 경우는 melt와 dcast 함수를 여러 단계에 걸쳐 사용하고, 결과를 rbind 해서 결합한다.
이런 유형의 작업에 유용한 다른 팩키지는 tidyr 과 splitstackshape이 있다.