[r] rbindlist가 rbind보다“더 나은”이유는 무엇입니까?

나는 문서화를 진행 data.table중이며 여기 SO에 대한 일부 대화에서 rbindlist보다 나은 것으로 나타났습니다 rbind.

나는 왜 왜 어떤 시나리오 가 rbindlist더 뛰어나고 rbind어떤 시나리오가 rbindlist실제로 뛰어 rbind납니까?

메모리 활용 측면에서 이점이 있습니까?



답변

rbindlist의 최적화 된 버전으로 do.call(rbind, list(...)), 사용시 속도가 느린 것으로 알려져 있습니다.rbind.data.frame


실제로 어디에서 뛰어 납니까

rbindlist빛나는 곳을 보여주는 몇 가지 질문

행별로 데이터 목록을 벡터화 한 빠른 병합

do.call 및 ldply를 사용하여 긴 데이터 프레임 목록 (~ 1 백만)을 단일 데이터 프레임으로 변환하는 데 문제가 있습니다.

여기에는 얼마나 빠른지 보여주는 벤치 마크가 있습니다.


rbind.data.frame이 느린 이유

rbind.data.frame많은 검사를 수행하며 이름으로 일치합니다. (즉, rbind.data.frame은 열의 순서가 다르고 이름별로 일치한다는 사실을 설명하고) rbindlist이러한 종류의 검사를 수행하지 않으며 위치별로 조인합니다.

예 :

do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
##    a b
## 1  1 2
## 2  2 3
## 3  2 1
## 4  3 2

rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
##     a b
##  1: 1 2
##  2: 2 3
##  3: 1 2
##  4: 2 3

rbindlist의 다른 제한 사항

그것은 하는 데 사용 처리하는 투쟁 factors으로 인해 수정 된 이후이 버그로 :

rbindlist 두 개의 data.tables 중 하나에는 요인이 있고 다른 하나에는 열에 대한 문자 유형이 있습니다 ( 버그 # 2650 )

중복 된 열 이름에 문제가 있습니다

참조
경고 메시지 : rbindlist에 (allargs) : data.table 가능한 버그 : 강압에 의해 도입의 NA? ( 버그 # 2384 )


rbind.data.frame 행 이름이 실망 스러울 수 있습니다

rbindlistlists data.frames및 을 처리 할 수 data.tables있으며 행 이름없이 data.table을 반환합니다.

당신은 do.call(rbind, list(...))
참조를 사용하여 행 이름의 뭉치에 들어갈 수 있습니다

do.call 내부에서 rbind를 사용할 때 행 이름을 바꾸는 것을 피하는 방법은 무엇입니까?


메모리 효율

메모리 측면에서 rbindlist구현 C되므로 메모리 효율적이므로 setattr참조로 속성을 설정 하는 데 사용 됩니다.

rbind.data.frame의 구현 R, 그것은 할당을 많이하고, 사용하지 않습니다 attr<-(그리고 class<-rownames<-(내부적으로) 생성 data.frame의 복사본을 만들 것이다 모두를.


답변

함으로써 v1.9.2,rbindlist 같은 많은 기능을 구현하면서 상당히 발전했습니다.

또한 v1.9.2 , rbind.data.table또한 얻은 fillR. 구현 누락 된 열을 작성하여 바인드 할 수 있습니다 인수를,

지금에 v1.9.3 기존 기능에 대해 더 많은 개선 사항이 있습니다.

  • rbindlist 논증을 얻다 use.names기본적으로 FALSE이전 버전과의 호환성을위한 .
  • rbindlist 또한 논쟁을 얻는다 fill 기본적으로 FALSE이전 버전과의 호환성도 있습니다.
  • 이러한 기능은 모두 C로 구현되며 기능을 추가하는 동안 속도가 저하되지 않도록주의해서 작성되었습니다.
  • 때문에 rbindlist지금은 이름과 채우기없는 열을 기준으로 일치시킬 수 있습니다, rbind.data.table단지 호출 rbindlist지금. 유일한 차이점은 use.names=TRUE기본적으로 rbind.data.table이전 버전과의 호환성을 위해입니다.

rbind.data.frame(C로 이동하여) 피할 수있는 사본 (@mnel도 지적 함)으로 인해 상당히 느려집니다. 그게 유일한 이유는 아니라고 생각합니다. 열 이름 확인 / 일치에 대한 구현rbind.data.framedata.frame 당 많은 열이 있고 바인딩 할 많은 data.frame이있는 경우 도 느려질 수 있습니다 (아래 벤치 마크 참조).

그러나 rbindlist요소 수준 확인 또는 이름 일치와 같은 특정 기능 이 부족하면 (보다) 빠를수록 가중치가 매우 작거나 없습니다 rbind.data.frame. 속도와 메모리에 최적화 된 C로 신중하게 구현 되었기 때문입니다.

다음은 rbindlistuse.names기능을 사용하여 열 이름으로 일치하는 동안 효율적인 바인딩을 강조하는 벤치 마크입니다 v1.9.3. 데이터 세트는 크기가 10 * 500 인 10000 개의 데이터 프레임으로 구성됩니다.

NB :이 벤치 마크에 대한 비교를 포함하도록 업데이트되었습니다 dplyrs ‘을 (를)bind_rows

library(data.table) # 1.11.5, 2018-06-02 00:09:06 UTC
library(dplyr) # 0.7.5.9000, 2018-06-12 01:41:40 UTC
set.seed(1L)
names = paste0("V", 1:500)
cols = 500L
foo <- function() {
    data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10))))
    setnames(data, sample(names))
}
n = 10e3L
ll = vector("list", n)
for (i in 1:n) {
    .Call("Csetlistelt", ll, i, foo())
}

system.time(ans1 <- rbindlist(ll))
#  user  system elapsed 
# 1.226   0.070   1.296 

system.time(ans2 <- rbindlist(ll, use.names=TRUE))
#  user  system elapsed 
# 2.635   0.129   2.772 

system.time(ans3 <- do.call("rbind", ll))
#   user  system elapsed 
# 36.932   1.628  38.594 

system.time(ans4 <- bind_rows(ll))
#   user  system elapsed 
# 48.754   0.384  49.224 

identical(ans2, setDT(ans3))
# [1] TRUE
identical(ans2, setDT(ans4))
# [1] TRUE

이름을 확인하지 않고 열을 바인딩하는 데는 1.3이 걸리고 열 이름을 확인하고 바인딩하는 데 1.5 초가 더 걸렸습니다. 기본 솔루션에 비해 14 배 빠르며 dplyr버전 보다 18 배 빠릅니다 .


답변