R 为什么seq(x)比1:length(x)慢得多?

R 为什么seq(x)比1:length(x)慢得多?,r,R,我最近回答了一个关于for循环的问题。在测试代码的速度时,我注意到在for循环中使用seq()而不是:大大降低了速度 看看这个非常简单的例子。f1()和f2()之间唯一的区别是循环序列的变化,然而f1()的速度是f2()的两倍多 f1seq是一种通用的S3方法,因此可能会浪费一些时间。 seq.默认值几乎有100行 您可能已经知道了seq_along,它直接调用.Primitive,比1:length(x)好一点,我发现的长循环的最佳方法是: f3 <- function(){

我最近回答了一个关于
for
循环的问题。在测试代码的速度时,我注意到在
for
循环中使用
seq()
而不是
大大降低了速度

看看这个非常简单的例子。
f1()
f2()
之间唯一的区别是
循环序列的
变化,然而
f1()
的速度是
f2()
的两倍多


f1
seq
是一种通用的S3方法,因此可能会浪费一些时间。
seq.默认值
几乎有100行

您可能已经知道了
seq_along
,它直接调用
.Primitive
,比
1:length(x)
好一点,我发现的长循环的最佳方法是:

f3 <- function(){
      x <- 1:5; y <- numeric(length(x))
      for(i in seq_along(x)) y[i] <- x[i]^2
      y
  }
>  microbenchmark(f1(), f3())
Unit: microseconds
 expr    min     lq median     uq    max neval
 f1() 27.095 27.916 28.327 29.148 89.495   100
 f3() 26.684 27.505 27.916 28.327 36.538   100

f3使用
seq\u len
您可以获得与
操作符几乎相同的时间:
操作符:

f3 <- function(){
  x <- 1:5; y <- numeric(length(x))
  for(i in seq_len(length(x))) y[i] <- x[i]^2
  y
}

library(microbenchmark)
microbenchmark(f1(), f2(),f3())

Unit: microseconds
 expr    min      lq  median     uq    max neval
 f1()  9.988 10.6855 10.9650 11.245 50.704   100
 f2() 23.257 23.7465 24.0605 24.445 88.140   100
 f3() 10.127 10.5460 10.7555 11.175 18.857   100

f3速度较慢的更具体原因:

seq(x)
将调用
seq.default
*,
seq.default
调用
1L:x

序列默认值

if ((One <- nargs() == 1L) && !missing(from)) {
    lf <- length(from)
    return(if (mode(from) == "numeric" && lf == 1L) {
        #checks validity -- more slow-down
        if (!is.finite(from)) stop("'from' cannot be NA, NaN or infinite")
        #boom! under the hood, seq.default is doing 1:N
        1L:from
    #looks like it defaults to seq_along if length(from) > 1?
    } else if (lf) 1L:lf else integer())
}
if((一个
if ((One <- nargs() == 1L) && !missing(from)) {
    lf <- length(from)
    return(if (mode(from) == "numeric" && lf == 1L) {
        #checks validity -- more slow-down
        if (!is.finite(from)) stop("'from' cannot be NA, NaN or infinite")
        #boom! under the hood, seq.default is doing 1:N
        1L:from
    #looks like it defaults to seq_along if length(from) > 1?
    } else if (lf) 1L:lf else integer())
}