[R] 여러개의 데이터프레임을 한꺼번에 하나의 데이터프레임으로 묶기, data.table package : rbindlist(data)
R 분석과 프로그래밍/R 프로그래밍 2016. 7. 10. 16:49이번 포스팅에서는 여러개의 데이터 프레임을 한꺼번에 하나의 데이터프레임으로 묶는 몇가지 방법을 알아보고, 성능 측면을 비교해보겠습니다.
이번 포스팅은 andrew 님이 r-bloggers.com 에 썼던 글을 그대로 가져다가 번역을 한 내용입니다.
[ Source ] Concatenating a list of data frames , June 6, 2014, By andrew
결론 먼저 말씀드리면, data.table package의 rbindlist(data) 함수가 속도 면에서 월등히 빠르네요.
[ R로 여러개의 데이터프레임을 한꺼번에 하나의 데이터프레임으로 묶기 ]
0) 문제 (The problem)
아래처럼 3개의 칼럼으로 구성된 100,000 개의 자잘한 데이터 프레임을 한개의 커다란 데이터 프레임으로 합치는 것이 풀어야 할 문제, 미션입니다.
data = list() 로 해서 전체 데이터 프레임들을 data라는 리스트로 만들어서 아래 각 방법별 예제에 사용하였습니다.
> ########################################### > ## Concatenating a list of data frames > ## do.call(rbind, data) > ## ldply(data, rbind) > ## rbind.fill(data) > ## rbindlist(data) ** winner! ** > ########################################### > > ## The Problem > > data = list() > > N = 100000 > > for (n in 1:N) { + data[[n]] = data.frame(index = n, + char = sample(letters, 1), + z = runif(1)) + } > > data[[1]] index char z 1 1 j 0.2300154
|
1) The navie solution : do.call(rbind, data)
가장 쉽게 생각할 수 있는 방법으로 base package에 포함되어 있는 rbind() 함수를 do.call 함수로 계속 호출해서 여러개의 데이터 프레임을 위/아래로 합치는 방법입니다.
이거 한번 돌리니 정말 시간 오래 걸리네요. @@~ 낮잠 잠깐 자고 와도 될 정도로요.
> ## (1) The Naive Solution > head(do.call(rbind, data)) index char z 1 1 j 0.23001541 2 2 f 0.63555284 3 3 d 0.65774397 4 4 y 0.46550511 5 5 b 0.02688307 6 6 u 0.19057217 |
2-1) plyr package : ldply(data, rbind)
두번째 방법은 plyr package의 ldply(data, rbind) 함수를 사용하는 방법입니다.
> ## (2) Alternative Solutions #1 and #2 > ## (2-1) plyr package : ldply(data, rbind) > install.packages("plyr") > library(plyr) > head(ldply(data, rbind)) index char z 1 1 j 0.23001541 2 2 f 0.63555284 3 3 d 0.65774397 4 4 y 0.46550511 5 5 b 0.02688307 6 6 u 0.19057217
|
2-2) plyr package : rbind.fill(data)
세번째 방법은 plyr package의 rbind.fill(data) 함수를 사용하는 방법입니다. 결과는 앞의 두 방법과 동일함을 알 수 있습니다.
> ## (2-2) plyr package : rbind.fill(data) > library(plyr) > head(rbind.fill(data)) index char z 1 1 j 0.23001541 2 2 f 0.63555284 3 3 d 0.65774397 4 4 y 0.46550511 5 5 b 0.02688307 6 6 u 0.19057217 |
3) data.table package : rbindlist(data)
마지막 방법은 data.table package의 rbindlist(data) 함수를 사용하는 방법입니다.
> ## (3) Alternative Solution > ## data.table package : rbindlist(data) > install.packages("data.table") > library(data.table) > head(rbindlist(data)) index char z 1: 1 j 0.23001541 2: 2 f 0.63555284 3: 3 d 0.65774397 4: 4 y 0.46550511 5: 5 b 0.02688307 6: 6 u 0.19057217 |
4) 벤치마킹 테스트 (bechmarking test)
> ## Benchmarking (performance comparison) > install.packages("rbenchmark") > library(rbenchmark) > benchmark(do.call(rbind, data), + ldply(data, rbind), + rbind.fill(data), + rbindlist(data)) test replications elapsed relative user.self sys.self user.child sys.child 1 do.call (rbind, data) 100 11387.82 668.692 11384.15 1.54 NA NA 2 ldply (data, rbind) 100 4983.72 292.644 4982.90 0.52 NA NA 3 rbind.fill (data) 100 1480.46 86.932 1480.23 0.17 NA NA 4 rbindlist (data) 100 17.03 1.000 16.86 0.17 NA NA |
패키지/함수별 성능 비교를 해본 결과 data.table 패키지의 rbindlist(data) 함수가 월등히 빠르다는 것을 알 수 있습니다. 위의 벤치마킹 결과를 보면, 속도가 가장 빨랐던 rbindlist(data)를 1로 놨을 때, 상대적인 속도(relative 칼럼)를 보면 rbind.fill(data)가 86.932로서 rbindlist(data)보다 86배 더 오래걸리고, ldply(data, rbind)가 292.644로서 rbindlist(data)보다 292배 더 오래걸린다는 뜻입니다. do.call(rbind, data)는 rbindlist(data) 보다 상대적으로 668.692배 더 시간이 걸리는 것으로 나오네요.
rbindlist(data)가 훨등히 속도가 빠른 이유는 두가지인데요,
(1) rbind() 함수가 각 데이터 프레임의 칼럼 이름을 확인하고, 칼럼 이름이 다를 경우 재정렬해서 합치는데 반해, data.table 패키지의 rbindlist() 함수는 각 데이터 프레임의 칼럼 이름을 확인하지 않고 단지 위치(position)를 기준으로 그냥 합쳐버리기 때문이며,
(따라서, rbindlist() 함수를 사용하려면 각 데이터 프레임의 칼럼 위치가 서로 동일해야 함)
(2) rbind() 함수는 R code로 작성된 반면에, data.table 패키지의 rbindlist() 는 C 언어로 코딩이 되어있기 때문입니다.
많은 도움이 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾸욱 눌러주세요.
'R 분석과 프로그래밍 > R 프로그래밍' 카테고리의 다른 글
[R 프로그래밍] 반복문과 조건문을 써서 벡터에서 0이 연속 3번 나오면 구간 나누기 (6) | 2018.02.02 |
---|---|
[R] 데이터프레임 다수 item을 가진 문자형 변수를 분리 후에 세로로 재구조화하기 (11) | 2016.09.29 |
[R] 폴더 내 여러개 파일들을 Loop 돌려서 자동으로 불러오기 (154) | 2016.07.02 |
R "target of assignment expands to non-language object" error : assign() (2) | 2015.09.22 |
ggplot2 저장 : ggsave(), console 내용 text 저장 : capture.output() (0) | 2015.09.17 |