在R中重复replicate()而没有循环

时间:2016-10-12 14:18:37

标签: r loops

这个问题主要是为了学习优秀的R编程实践。我想对复制函数中表达式的单个变量的不同输入重复replicate函数。我可以使用for循环轻松完成此操作,但我反复听说如果我在R中使用for循环,我做错了。 有没有办法在没有循环的情况下使用不同的输入重复调用replicate之后,到目前为止,我有最好的尝试。

循环工作代码:

set.seed(1564) #Birth of Galileo!
x <- rnorm(1000, 15, 3)
y <- 2*x + rnorm(1000, 0, 5)

cor(x, y)

cor.fxn <- function(N, x, y) {
  samp.row <- sample(1:1000, N)
  cor(x[samp.row], y[samp.row])
}

N.list <- seq(3,20)
cor.list <- rep(NA_real_, length(N.list))
for (N in N.list){
  cor.resamp <- replicate(1000, cor.fxn(N, x, y))
  cor.list[N-2] <- median(cor.resamp)
}
plot(N.list, cor.list)

没有循环的非功能性最佳尝试:

set.seed(1564) #Birth of Galileo!
x <- rnorm(1000, 15, 3)
y <- 2*x + rnorm(1000, 0, 5)
X <- list(3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
eggs <- lapply(X, replicate, n=1000, expr=cor.fxn, x=x, y=y)

哪个会出错:

Error in FUN(X[[i]], ...) : 
  unused arguments (x = c(9.17486389116665, 13.6573453081421, 12.2166561575586, 11.3619489970582, 17.9998611075272, 11.1171958860255, 20.4489048239365, 16.8825343591062, 12.9990097472942, 12.5617129892976, 10.9833420846924, 13.7732692244654, 16.9641205588413, 11.1309409503371, 11.7859737745279,...

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

R中的循环速度很慢,但您可能没有听到的另一部分是您应该对您的操作进行矢量化。 * apply系列函数本身并不比for循环快。让我们看看一些基准

# Boiler plate code used for both functions

cor.fxn <- function(N, x, y) {
  samp.row <- sample(1:1000, N)
  cor(x[samp.row], y[samp.row])
}

set.seed(1564) #Birth of Galileo!
x <- rnorm(1000, 15, 3)
y <- 2*x + rnorm(1000, 0, 5)
N.list <- seq(3,20)

# Using 'for loop'
foo_a = function(....) {cor.list <- rep(NA_real_, length(N.list)); 
                          for (N in N.list) {
                            cor.resamp <- replicate(1000, cor.fxn(N, x, y))
                            cor.list[N-2] <- median(cor.resamp)
                          }
        }

# Using sapply
foo_b = function(...) sapply(3:20, function(n) median(replicate(1000, cor.fxn(n, x, y))))

microbenchmark(foo_a(), foo_b(), times = 100L)

如上所述,看起来两种方法之间的时间没有区别。

Unit: milliseconds
    expr      min       lq     mean   median       uq      max neval
 foo_a() 939.7068 1041.964 1140.159 1146.065 1243.540 1367.411   100
 foo_b() 936.5962 1045.023 1138.337 1133.074 1239.099 1334.430   100

这个特定的测试用例无法进行矢量化,因为您需要处理1000次运行的中位数。这篇文章的重点是要指出for循环并不比在R中应用族函数差。但是,在可能的情况下,你应该总是在循环/应用解决方案上寻找矢量化解决方案。