[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 NA2 ldply(data, rbind) 100 4983.72 292.644 4982.90 0.52 NA NA3 rbind.fill(data) 100 1480.46 86.932 1480.23 0.17 NA NA4 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 |

