<div>
Hi everybody,
</div><div><br></div><div>I think there's a faster version of "CJ" function that's possible. The issue currently is that the "sort" is done at the very end by using `setkey` which will work on the data *after* getting all the combinations, and therefore sorting a huge amount of entries.</div><div><br></div><div>However, a faster way would be to get it first sorted (even before working out all combinations) and then use the hack:</div><div><br></div><div>setattr(l, 'sorted', names(l))</div><div><br></div><div>Basically there are just 2 lines that need change (see bottom of the post).</div><div><br></div><div>---------</div><div>Here's first some benchmarks on `CJ_fast` (see below) and `CJ` on a relatively big data:</div><div><br></div><div>w <- sample(1e4, 1e3)</div><div>x <- sample(letters, 12)</div><div>y <- sample(letters, 12)</div><div>z <- sample(letters, 12)</div><div><br></div><div>system.time(t1 <- do.call(CJ, list(w,x,y,z)))</div><div><div> user system elapsed </div><div> 0.775 0.052 0.835 </div></div><div>system.time(t2 <- do.call(CJ_fast, list(w,x,y,z)))</div><div><div> user system elapsed </div><div> 0.220 0.001 0.221 </div></div><div><br></div><div>identical(t1, t2)</div><div>[1] TRUE</div><div>---------</div><div><br></div>
<div><div>The function: (there are only two changes)</div><div><br></div><div><div>CJ_fast <- function (...) </div><div>{</div><div> l = list(...)</div><div> if (length(l) > 1) {</div><div> n = sapply(l, length)</div><div> nrow = prod(n)</div><div> x = c(rev(data.table:::take(cumprod(rev(n)))), 1L)</div><div> # 1) SORT HERE</div><div> for (i in seq(along = x)) l[[i]] = rep(sort(l[[i]], na.last = TRUE), each = x[i], </div><div> length = nrow)</div><div> }</div><div> setattr(l, "row.names", .set_row_names(length(l[[1]])))</div><div> setattr(l, "class", c("data.table", "data.frame"))</div><div> vnames = names(l)</div><div> if (is.null(vnames)) </div><div> vnames = rep("", length(l))</div><div> tt = vnames == ""</div><div> if (any(tt)) {</div><div> vnames[tt] = paste("V", which(tt), sep = "")</div><div> setattr(l, "names", vnames)</div><div> }</div><div> data.table:::settruelength(l, 0L)</div><div> l = alloc.col(l)</div><div> # 2) REPLACE SETKEY WITH ATTRIBUTE "SORTED"</div><div> setattr(l, 'sorted', names(l))</div><div> l</div><div>}</div></div><div><br></div><div>Arun</div><div><br></div></div>