일치 접근 방식은 첫 번째 데이터 프레임의 각 키 값에 대해 두 번째 데이터 프레임에 고유 한 키가있을 때 작동합니다. 두 번째 데이터 프레임에 중복이있는 경우 일치 및 병합 방식이 동일하지 않습니다. 물론 매치는 그렇게 많이하지 않기 때문에 더 빠릅니다. 특히 중복 키를 찾지 않습니다. (코드 뒤에 계속)
DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
b a c
1 1 1 a
2 2 1 b
3 3 2 c
4 3 2 d
5 4 2 e
DF1$c = DF2$c[match(DF1$b, DF2$b)]
DF1$c
[1] a b c e
Levels: a b c d e
> DF1
a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e
질문에 게시 된 sqldf 코드에서 인덱스가 두 테이블에 사용 된 것처럼 보일 수 있지만 실제로는 SQL select가 실행되기 전에 덮어 쓴 테이블에 배치되며 부분적으로 그 이유를 설명합니다. 너무 느립니다. sqldf의 아이디어는 R 세션의 데이터 프레임이 sqlite의 테이블이 아닌 데이터베이스를 구성한다는 것입니다. 따라서 코드가 정규화되지 않은 테이블 이름을 참조 할 때마다 sqlite의 기본 데이터베이스가 아닌 R 작업 공간에서 찾습니다. 따라서 표시된 select 문은 작업 공간에서 d1 및 d2를 인덱스와 함께 있던 데이터베이스를 막는 sqlite의 주 데이터베이스로 읽습니다. 결과적으로 인덱스가없는 조인을 수행합니다. sqlite의 주 데이터베이스에있는 d1 및 d2 버전을 사용하려면 해당 버전을 main.d1 및 main으로 참조해야합니다. d2는 d1 및 d2가 아닙니다. 또한 가능한 한 빨리 실행하려는 경우 간단한 조인은 두 테이블 모두에서 인덱스를 사용할 수 없으므로 인덱스 중 하나를 만드는 시간을 절약 할 수 있습니다. 아래 코드에서 이러한 점을 설명합니다.
정확한 계산이 어떤 패키지가 가장 빠른지 큰 차이를 만들 수 있다는 것을 알아 차릴 가치가 있습니다. 예를 들어, 아래에서 병합 및 집계를 수행합니다. 우리는 두 결과가 거의 반대임을 알 수 있습니다. 가장 빠른 것에서 가장 느린 것까지의 첫 번째 예에서는 data.table, plyr, merge 및 sqldf를 얻는 반면 두 번째 예에서는 sqldf, aggregate, data.table 및 plyr-첫 번째 예와 거의 반대입니다. 첫 번째 예에서 sqldf는 data.table보다 3 배 느리고 두 번째 예에서는 plyr보다 200 배 빠르며 data.table보다 100 배 빠릅니다. 아래에서는 입력 코드, 병합에 대한 출력 타이밍 및 집계에 대한 출력 타이밍을 보여줍니다. 또한 sqldf가 데이터베이스를 기반으로하므로 R이 처리 할 수있는 것보다 큰 개체를 처리 할 수 있다는 점도 주목할 가치가 있습니다 (sqldf의 dbname 인수를 사용하는 경우). 다른 접근 방식은 주 메모리에서 처리하는 것으로 제한됩니다. 또한 sqlite로 sqldf를 설명했지만 H2 및 PostgreSQL 데이터베이스도 지원합니다.
library(plyr)
library(data.table)
library(sqldf)
set.seed(123)
N <- 1e5
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(d1, g1, g2)
library(rbenchmark)
benchmark(replications = 1, order = "elapsed",
merge = merge(d1, d2),
plyr = join(d1, d2),
data.table = {
dt1 <- data.table(d1, key = "x")
dt2 <- data.table(d2, key = "x")
data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
},
sqldf = sqldf(c("create index ix1 on d1(x)",
"select * from main.d1 join d2 using(x)"))
)
set.seed(123)
N <- 1e5
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)
benchmark(replications = 1, order = "elapsed",
aggregate = aggregate(d[c("x", "y")], d[c("g1", "g2")], mean),
data.table = {
dt <- data.table(d, key = "g1,g2")
dt[, colMeans(cbind(x, y)), by = "g1,g2"]
},
plyr = ddply(d, .(g1, g2), summarise, avx = mean(x), avy=mean(y)),
sqldf = sqldf(c("create index ix on d(g1, g2)",
"select g1, g2, avg(x), avg(y) from main.d group by g1, g2"))
)
병합 계산을 비교하는 두 벤치 마크 호출의 출력은 다음과 같습니다.
Joining by: x
test replications elapsed relative user.self sys.self user.child sys.child
3 data.table 1 0.34 1.000000 0.31 0.01 NA NA
2 plyr 1 0.44 1.294118 0.39 0.02 NA NA
1 merge 1 1.17 3.441176 1.10 0.04 NA NA
4 sqldf 1 3.34 9.823529 3.24 0.04 NA NA
집계 계산을 비교하는 벤치 마크 호출의 출력은 다음과 같습니다.
test replications elapsed relative user.self sys.self user.child sys.child
4 sqldf 1 2.81 1.000000 2.73 0.02 NA NA
1 aggregate 1 14.89 5.298932 14.89 0.00 NA NA
2 data.table 1 132.46 47.138790 131.70 0.08 NA NA
3 plyr 1 212.69 75.690391 211.57 0.56 NA NA