我正在寻找尽可能快的速度,并留在基地做什么expand.grid
.我过去曾outer
用于类似的目的来创建一个向量; 这样的事情:
v <- outer(letters, LETTERS, paste0)
unlist(v[lower.tri(v)])
Run Code Online (Sandbox Code Playgroud)
基准测试表明我outer
可以快得多,expand.grid
但这次我想创建两个列,就像expand.grid
(2个向量的所有可能的组合)一样,但是我的方法outer
与外部这个时候没有基准.
我希望采用2个向量并尽可能快地创建每个可能的组合作为两列(我认为outer
可能是路线,但对任何基本方法都是敞开的.
这是expand.grid
方法和outer
方法.
dat <- cbind(mtcars, mtcars, mtcars)
expand.grid(seq_len(nrow(dat)), seq_len(ncol(dat)))
FOO <- function(x, y) paste(x, y, sep=":")
x <- outer(seq_len(nrow(dat)), seq_len(ncol(dat)), FOO)
apply(do.call("rbind", strsplit(x, ":")), 2, as.integer)
Run Code Online (Sandbox Code Playgroud)
微基准测试显示outer
较慢:
# expr min lq median uq max
# EXPAND.G 812.743 838.6375 894.6245 927.7505 27029.54
# OUTER 5107.871 5198.3835 5329.4860 5605.2215 27559.08
Run Code Online (Sandbox Code Playgroud)
我认为我的outer
使用很慢,因为我不知道如何使用outer
直接创建一个长度为2的向量,我可以do.call('rbind'
在一起.我必须缓慢paste
和缓慢分裂.我怎么能用比outer
(或其他方法base
)更快的方式做到这一点expand grid
?
编辑:添加微基准测试结果.
**
Unit: microseconds
expr min lq median uq max
1 ERNEST 34.993 39.1920 52.255 57.854 29170.705
2 JOHN 13.997 16.3300 19.130 23.329 266.872
3 ORIGINAL 352.720 372.7815 392.377 418.738 36519.952
4 TOMMY 16.330 19.5960 23.795 27.061 6217.374
5 VINCENT 377.447 400.3090 418.505 451.864 43567.334
Run Code Online (Sandbox Code Playgroud)
**
Joh*_*ohn 16
文档rep.int
并不完整.在最常见的情况下,它不仅仅是最快的,因为您可以为times参数传递向量,就像使用rep
.对于这两个序列,你可以直接使用它,比Tommy的时间减少40%左右.
expand.grid.jc <- function(seq1,seq2) {
cbind(Var1 = rep.int(seq1, length(seq2)),
Var2 = rep.int(seq2, rep.int(length(seq1),length(seq2))))
}
Run Code Online (Sandbox Code Playgroud)
Ern*_*t A 15
使用rep.int
:
expand.grid.alt <- function(seq1,seq2) {
cbind(rep.int(seq1, length(seq2)),
c(t(matrix(rep.int(seq2, length(seq1)), nrow=length(seq2)))))
}
expand.grid.alt(seq_len(nrow(dat)), seq_len(ncol(dat)))
Run Code Online (Sandbox Code Playgroud)
在我的电脑上比它快6倍expand.grid
.
@ErnestA有一个很好的解决方案,非常值得您回答!
...虽然可能略快一些:
expand.grid.alt2 <- function(seq1,seq2) {
cbind(Var1=rep.int(seq1, length(seq2)), Var2=rep(seq2, each=length(seq1)))
}
s1=seq_len(2000); s2=seq_len(2000)
system.time( for(i in 1:10) expand.grid.alt2(s1, s2) ) # 1.58
system.time( for(i in 1:10) expand.grid.alt(s1, s2) ) # 1.75
system.time( for(i in 1:10) expand.grid(s1, s2) ) # 2.46
Run Code Online (Sandbox Code Playgroud)