재현가능한 과학적 분석을 위한 중급 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이 있다.