R 有没有办法说“做 n 次”而不必编写带有冗余变量的 for 循环?

J. *_*ini 5 for-loop r apply control-flow

我最近写了这行代码:for(i in seq_len(exponent)){out<-squareMat%*%out}. 显然,i从来没有用过,我只是想说“exponent次,做out<-squareMat%*%out”。没有多余的计数器,有没有办法做到这一点i?例如,是否有一个apply家庭功能?

示例 - 我有:

squareMat<-matrix(c(0,10,20,30),2,2)
out<-diag(nrow = nrow(squareMat))
exponent<-5
for(i in seq_len(exponent)){out<-squareMat%*%out}
out
Run Code Online (Sandbox Code Playgroud)

我想要的是:

squareMat<-matrix(c(0,10,20,30),2,2)
out<-diag(nrow = nrow(squareMat))
exponent<-5
[do exponent times]{out<-squareMat%*%out}
out
Run Code Online (Sandbox Code Playgroud)

lcg*_*doy 6

是的,它确实。baseR中有几个有用的函数,这些函数现在不常用了。其中之一正是您想要的。该replicate函数复制表达式 ( expr)n次。它的工作原理如下,假设我想从均匀(0 到 1)分布中生成 3 个大小为 5 的不同样本。使用replicate. 看看下面的一段代码

replicate(n = 3, expr = {runif(n = 5)})
#            [,1]      [,2]       [,3]
# [1,] 0.1944426 0.5158065 0.39892501
# [2,] 0.5676580 0.9940599 0.97385575
# [3,] 0.5570141 0.2274214 0.60239883
# [4,] 0.5074303 0.3526040 0.95445298
# [5,] 0.1931812 0.4593620 0.03283596
Run Code Online (Sandbox Code Playgroud)

结果会自动组织在array(在这种情况下为矩阵)中。但是,您可以设置参数simplify = FALSE。然后,返回将是一个列表

replicate(n = 3, expr = {runif(n = 5)}, simplify = FALSE)
# [[1]]
# [1] 0.4694347 0.9559887 0.8110113 0.7528089 0.6639614
# 
# [[2]]
# [1] 0.8731027 0.7295846 0.3773571 0.5394776 0.6792322
# 
# [[3]]
# [1] 0.3463870 0.3776352 0.3895620 0.2166284 0.5065204
Run Code Online (Sandbox Code Playgroud)

重要的是要注意这些复制中的每一个都是相互独立的。如果您希望按顺序复制某些内容,则必须使用for循环或其他合适的函数。例如,存在一个名为rapply(recursive lapply)的函数。但是,我一直不清楚使用它的最佳方式。


Wal*_*ldi 6

对于像%*%您可以使用Reduce, optionalyinit参数的二元运算(实际上这里不需要,因为init是单位矩阵,请参阅@nicola 的评论,但使答案更一般):

squareMat<-matrix(c(0,10,20,30),2,2)
exponent<-5
Reduce('%*%', init = diag(nrow = nrow(squareMat)), replicate(exponent, squareMat, simplify=F))
#>          [,1]     [,2]
#> [1,]  7800000 27800000
#> [2,] 13900000 49500000
Run Code Online (Sandbox Code Playgroud)

这可以通过replicate在计算中不使用第二个参数(1:exponent仅用作计数器)来加速避免调用:

Reduce(function(x,notused) {squareMat %*% x}, init = diag(nrow = nrow(squareMat)), 1:exponent)
#>          [,1]     [,2]
#> [1,]  7800000 27800000
#> [2,] 13900000 49500000
Run Code Online (Sandbox Code Playgroud)

请注意,Reduce在这种情况下,它的效率低于简单循环,因此,有趣但可能不是最佳的:

microbenchmark::microbenchmark(test_reduce(),test_reduce2(),test_loop())
Unit: microseconds
           expr  min   lq   mean median    uq  max neval cld
  test_reduce() 17.2 17.7 21.461   18.0 18.60 97.4   100   c
 test_reduce2()  7.9  8.4  9.463    8.6  8.85 25.9   100  b 
    test_loop()  3.0  3.2  3.786    3.3  3.40 26.2   100 a  
Run Code Online (Sandbox Code Playgroud)